mirror of
https://github.com/Laxilef/OTGateway.git
synced 2026-05-18 23:38:16 +05:00
Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| c6117f106e | |||
| 66a433e0dd | |||
| dcc9b37010 | |||
| 554342e7f5 |
@@ -1,152 +0,0 @@
|
|||||||
name: Build
|
|
||||||
|
|
||||||
on:
|
|
||||||
workflow_dispatch:
|
|
||||||
push:
|
|
||||||
paths-ignore:
|
|
||||||
- "assets/**"
|
|
||||||
- "tools/**"
|
|
||||||
- "**/*.md"
|
|
||||||
- "LICENSE"
|
|
||||||
|
|
||||||
pull_request:
|
|
||||||
paths-ignore:
|
|
||||||
- "assets/**"
|
|
||||||
- "tools/**"
|
|
||||||
- "**/*.md"
|
|
||||||
- "LICENSE"
|
|
||||||
|
|
||||||
concurrency:
|
|
||||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
|
||||||
cancel-in-progress: true
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
prepare:
|
|
||||||
name: Prepare (get envs)
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
outputs:
|
|
||||||
envs: ${{ steps.envs.outputs.envs }}
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@v6
|
|
||||||
|
|
||||||
- name: Python
|
|
||||||
uses: actions/setup-python@v6
|
|
||||||
with:
|
|
||||||
python-version: "3.x"
|
|
||||||
|
|
||||||
- name: Install PlatformIO Core
|
|
||||||
run: |
|
|
||||||
python -m pip install --upgrade pip
|
|
||||||
pip install --upgrade platformio
|
|
||||||
pip install --upgrade intelhex
|
|
||||||
|
|
||||||
- name: Get environments
|
|
||||||
id: envs
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
ENVS=$(
|
|
||||||
pio project config --json-output \
|
|
||||||
| jq -c '
|
|
||||||
.[]
|
|
||||||
| select(type == "array")
|
|
||||||
| .[0]
|
|
||||||
| select(startswith("env:"))
|
|
||||||
| sub("^env:"; "")
|
|
||||||
' | jq -s -c '.'
|
|
||||||
)
|
|
||||||
|
|
||||||
echo "envs=$ENVS" >> "$GITHUB_OUTPUT"
|
|
||||||
echo "$ENVS"
|
|
||||||
|
|
||||||
build:
|
|
||||||
name: Build ${{ matrix.env }}
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
needs: prepare
|
|
||||||
|
|
||||||
strategy:
|
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
|
||||||
env: ${{ fromJson(needs.prepare.outputs.envs) }}
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@v6
|
|
||||||
|
|
||||||
- name: Python
|
|
||||||
uses: actions/setup-python@v6
|
|
||||||
with:
|
|
||||||
python-version: "3.x"
|
|
||||||
|
|
||||||
- name: Install Node.js
|
|
||||||
uses: actions/setup-node@v5
|
|
||||||
with:
|
|
||||||
node-version: "22"
|
|
||||||
|
|
||||||
- name: Install PlatformIO Core
|
|
||||||
run: |
|
|
||||||
python -m pip install --upgrade pip
|
|
||||||
pip install --upgrade platformio
|
|
||||||
pip install --upgrade intelhex
|
|
||||||
|
|
||||||
- name: Full clean
|
|
||||||
run: |
|
|
||||||
pio run -e ${{ matrix.env }} -t fullclean
|
|
||||||
|
|
||||||
- name: Build firmware & filesystem
|
|
||||||
env:
|
|
||||||
PIOENV: ${{ matrix.env }}
|
|
||||||
run: |
|
|
||||||
pio run -e ${{ matrix.env }}
|
|
||||||
|
|
||||||
- name: Upload artifacts
|
|
||||||
uses: actions/upload-artifact@v7
|
|
||||||
with:
|
|
||||||
name: ${{ matrix.env }}
|
|
||||||
if-no-files-found: error
|
|
||||||
path: |
|
|
||||||
build/*.bin
|
|
||||||
build/*.elf
|
|
||||||
|
|
||||||
release:
|
|
||||||
name: Release Dev
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
needs: build
|
|
||||||
permissions:
|
|
||||||
contents: write
|
|
||||||
if: ${{ github.repository_owner == 'Laxilef' && github.ref == 'refs/heads/async' }}
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Download artifacts
|
|
||||||
uses: actions/download-artifact@v5
|
|
||||||
with:
|
|
||||||
path: artifacts
|
|
||||||
merge-multiple: true
|
|
||||||
|
|
||||||
- name: Delete old release assets
|
|
||||||
uses: mknejp/delete-release-assets@v1
|
|
||||||
with:
|
|
||||||
token: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
tag: dev
|
|
||||||
fail-if-no-assets: false
|
|
||||||
fail-if-no-release: false
|
|
||||||
assets: |
|
|
||||||
*.bin
|
|
||||||
*.elf
|
|
||||||
|
|
||||||
- name: Publish Dev release
|
|
||||||
uses: softprops/action-gh-release@v3
|
|
||||||
with:
|
|
||||||
tag_name: dev
|
|
||||||
target_commitish: async
|
|
||||||
name: Dev (unstable)
|
|
||||||
prerelease: true
|
|
||||||
make_latest: false
|
|
||||||
generate_release_notes: true
|
|
||||||
files: |
|
|
||||||
artifacts/*.bin
|
|
||||||
artifacts/*.elf
|
|
||||||
@@ -1,110 +0,0 @@
|
|||||||
name: CI
|
|
||||||
on:
|
|
||||||
workflow_dispatch:
|
|
||||||
push:
|
|
||||||
pull_request:
|
|
||||||
|
|
||||||
concurrency:
|
|
||||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
|
||||||
cancel-in-progress: true
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
validate-json:
|
|
||||||
name: Validate JSON
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Checkout repository
|
|
||||||
uses: actions/checkout@v6
|
|
||||||
|
|
||||||
- name: Install jq
|
|
||||||
run: sudo apt-get update && sudo apt-get install -y jq
|
|
||||||
|
|
||||||
- name: Validate
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
set -euo pipefail
|
|
||||||
|
|
||||||
echo "Searching JSON files in src_data..."
|
|
||||||
|
|
||||||
files=$(find src_data -type f -iname "*.json")
|
|
||||||
|
|
||||||
if [ -z "$files" ]; then
|
|
||||||
echo "No JSON files found."
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
failed=0
|
|
||||||
|
|
||||||
for file in $files; do
|
|
||||||
echo "Validating: $file"
|
|
||||||
|
|
||||||
if ! jq empty "$file" >/dev/null 2>&1; then
|
|
||||||
echo "❌ Invalid JSON: $file"
|
|
||||||
failed=1
|
|
||||||
else
|
|
||||||
echo "✅ Valid JSON: $file"
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
if [ "$failed" -ne 0 ]; then
|
|
||||||
echo ""
|
|
||||||
echo "JSON validation failed."
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
echo "All JSON files are valid."
|
|
||||||
|
|
||||||
cpplint:
|
|
||||||
name: cpplint
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@v6
|
|
||||||
|
|
||||||
- name: Cache
|
|
||||||
uses: actions/cache@v5
|
|
||||||
with:
|
|
||||||
key: ${{ runner.os }}-cpplint
|
|
||||||
path: ~/.cache/pip
|
|
||||||
|
|
||||||
- name: Python
|
|
||||||
uses: actions/setup-python@v6
|
|
||||||
with:
|
|
||||||
python-version: "3.x"
|
|
||||||
|
|
||||||
- name: Install cpplint
|
|
||||||
run: |
|
|
||||||
python -m pip install --upgrade pip
|
|
||||||
pip install --upgrade cpplint
|
|
||||||
|
|
||||||
- name: cpplint
|
|
||||||
run: |
|
|
||||||
FILTERS="-legal/copyright,\
|
|
||||||
-runtime/int,\
|
|
||||||
-runtime/references,\
|
|
||||||
-runtime/indentation_namespace,\
|
|
||||||
-runtime/arrays,\
|
|
||||||
-runtime/printf,\
|
|
||||||
-whitespace/line_length,\
|
|
||||||
-whitespace/braces,\
|
|
||||||
-whitespace/comments,\
|
|
||||||
-whitespace/indent,\
|
|
||||||
-whitespace/newline,\
|
|
||||||
-whitespace/parens,\
|
|
||||||
-whitespace/blank_line,\
|
|
||||||
-readability/braces,\
|
|
||||||
-readability/todo,\
|
|
||||||
-readability/namespace,\
|
|
||||||
-build/header_guard,\
|
|
||||||
-build/include_subdir,\
|
|
||||||
-build/include_what_you_use,\
|
|
||||||
-build/namespaces,\
|
|
||||||
-build/c++11"
|
|
||||||
|
|
||||||
cpplint \
|
|
||||||
--repository=. \
|
|
||||||
--recursive \
|
|
||||||
--quiet \
|
|
||||||
--filter="$FILTERS" \
|
|
||||||
include lib src
|
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
class BufferedWebServer {
|
class BufferedWebServer {
|
||||||
public:
|
public:
|
||||||
explicit BufferedWebServer(WebServer* webServer, size_t bufferSize = 64) {
|
BufferedWebServer(WebServer* webServer, size_t bufferSize = 64) {
|
||||||
this->webServer = webServer;
|
this->webServer = webServer;
|
||||||
this->bufferSize = bufferSize;
|
this->bufferSize = bufferSize;
|
||||||
this->buffer = static_cast<uint8_t*>(malloc(bufferSize * sizeof(*this->buffer)));
|
this->buffer = (uint8_t*)malloc(bufferSize * sizeof(*this->buffer));
|
||||||
}
|
}
|
||||||
|
|
||||||
~BufferedWebServer() {
|
~BufferedWebServer() {
|
||||||
@@ -28,7 +28,7 @@ public:
|
|||||||
|
|
||||||
if (pretty) {
|
if (pretty) {
|
||||||
serializeJsonPretty(content, *this);
|
serializeJsonPretty(content, *this);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
serializeJson(content, *this);
|
serializeJson(content, *this);
|
||||||
}
|
}
|
||||||
@@ -99,4 +99,4 @@ protected:
|
|||||||
uint8_t* buffer;
|
uint8_t* buffer;
|
||||||
size_t bufferSize = 64;
|
size_t bufferSize = 64;
|
||||||
size_t bufferPos = 0;
|
size_t bufferPos = 0;
|
||||||
};
|
};
|
||||||
@@ -7,7 +7,7 @@ public:
|
|||||||
typedef std::function<void(unsigned long, uint8_t)> BeforeSendRequestCallback;
|
typedef std::function<void(unsigned long, uint8_t)> BeforeSendRequestCallback;
|
||||||
typedef std::function<void(unsigned long, unsigned long, OpenThermResponseStatus, uint8_t)> AfterSendRequestCallback;
|
typedef std::function<void(unsigned long, unsigned long, OpenThermResponseStatus, uint8_t)> AfterSendRequestCallback;
|
||||||
|
|
||||||
explicit CustomOpenTherm(int inPin = 4, int outPin = 5, bool isSlave = false, bool alwaysReceive = false) : OpenTherm(inPin, outPin, isSlave, alwaysReceive) {}
|
CustomOpenTherm(int inPin = 4, int outPin = 5, bool isSlave = false, bool alwaysReceive = false) : OpenTherm(inPin, outPin, isSlave, alwaysReceive) {}
|
||||||
~CustomOpenTherm() {}
|
~CustomOpenTherm() {}
|
||||||
|
|
||||||
CustomOpenTherm* setDelayCallback(DelayCallback callback = nullptr) {
|
CustomOpenTherm* setDelayCallback(DelayCallback callback = nullptr) {
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ public:
|
|||||||
if (this->publishEventCallback) {
|
if (this->publishEventCallback) {
|
||||||
this->publishEventCallback(topic, false);
|
this->publishEventCallback(topic, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -114,7 +114,7 @@ public:
|
|||||||
return topic;
|
return topic;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
String getDeviceTopic(T value, char dpvSeparator = '/') {
|
String getDeviceTopic(T value, char dpvSeparator = '/') {
|
||||||
String topic = "";
|
String topic = "";
|
||||||
topic.concat(this->devicePrefix);
|
topic.concat(this->devicePrefix);
|
||||||
@@ -147,7 +147,7 @@ public:
|
|||||||
return topic;
|
return topic;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class DT, class VT>
|
template <class DT, class VT>
|
||||||
String getEntityIdWithPrefix(DT domain, VT value, char separator = '_') {
|
String getEntityIdWithPrefix(DT domain, VT value, char separator = '_') {
|
||||||
String topic = "";
|
String topic = "";
|
||||||
topic.concat(domain);
|
topic.concat(domain);
|
||||||
@@ -158,7 +158,7 @@ public:
|
|||||||
return topic;
|
return topic;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
String getUniqueIdWithPrefix(T value, char separator = '_') {
|
String getUniqueIdWithPrefix(T value, char separator = '_') {
|
||||||
String topic = "";
|
String topic = "";
|
||||||
topic.concat(this->devicePrefix);
|
topic.concat(this->devicePrefix);
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#ifndef PROGMEM
|
#ifndef PROGMEM
|
||||||
#define PROGMEM // NOLINT
|
#define PROGMEM
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
const char HA_ENTITY_BINARY_SENSOR[] PROGMEM = "binary_sensor";
|
const char HA_ENTITY_BINARY_SENSOR[] PROGMEM = "binary_sensor";
|
||||||
|
|||||||
@@ -21,4 +21,4 @@ public:
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
@@ -12,10 +12,10 @@ public:
|
|||||||
typedef std::function<void(const char*, size_t, size_t, bool)> PublishEventCallback;
|
typedef std::function<void(const char*, size_t, size_t, bool)> PublishEventCallback;
|
||||||
typedef std::function<void(size_t, size_t)> FlushEventCallback;
|
typedef std::function<void(size_t, size_t)> FlushEventCallback;
|
||||||
|
|
||||||
explicit MqttWriter(MqttClient* client, size_t bufferSize = 64) {
|
MqttWriter(MqttClient* client, size_t bufferSize = 64) {
|
||||||
this->client = client;
|
this->client = client;
|
||||||
this->bufferSize = bufferSize;
|
this->bufferSize = bufferSize;
|
||||||
this->buffer = static_cast<uint8_t*>(malloc(bufferSize * sizeof(*this->buffer)));
|
this->buffer = (uint8_t*) malloc(bufferSize * sizeof(*this->buffer));
|
||||||
|
|
||||||
#ifdef ARDUINO_ARCH_ESP32
|
#ifdef ARDUINO_ARCH_ESP32
|
||||||
this->mutex = new std::mutex();
|
this->mutex = new std::mutex();
|
||||||
@@ -96,7 +96,7 @@ public:
|
|||||||
serializeJson(doc, *this);
|
serializeJson(doc, *this);
|
||||||
this->flush();
|
this->flush();
|
||||||
this->client->endMessage();
|
this->client->endMessage();
|
||||||
|
|
||||||
written = this->writeAfterLock;
|
written = this->writeAfterLock;
|
||||||
}
|
}
|
||||||
this->unlock();
|
this->unlock();
|
||||||
@@ -134,7 +134,7 @@ public:
|
|||||||
this->write(buffer, length);
|
this->write(buffer, length);
|
||||||
this->flush();
|
this->flush();
|
||||||
this->client->endMessage();
|
this->client->endMessage();
|
||||||
|
|
||||||
written = this->writeAfterLock;
|
written = this->writeAfterLock;
|
||||||
result = written == length;
|
result = written == length;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -74,7 +74,7 @@ void NetworkConnection::onEvent(System_Event_t *event) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -106,7 +106,7 @@ void NetworkConnection::onEvent(WiFiEvent_t event, WiFiEventInfo_t info) {
|
|||||||
rawDisconnectReason = info.wifi_sta_disconnected.reason;
|
rawDisconnectReason = info.wifi_sta_disconnected.reason;
|
||||||
disconnectReason = convertDisconnectReason(info.wifi_sta_disconnected.reason);
|
disconnectReason = convertDisconnectReason(info.wifi_sta_disconnected.reason);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -146,7 +146,7 @@ NetworkConnection::DisconnectReason NetworkConnection::convertDisconnectReason(u
|
|||||||
case WIFI_REASON_HANDSHAKE_TIMEOUT:
|
case WIFI_REASON_HANDSHAKE_TIMEOUT:
|
||||||
return DisconnectReason::HANDSHAKE_TIMEOUT;
|
return DisconnectReason::HANDSHAKE_TIMEOUT;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return DisconnectReason::OTHER;
|
return DisconnectReason::OTHER;
|
||||||
}
|
}
|
||||||
@@ -155,4 +155,4 @@ NetworkConnection::DisconnectReason NetworkConnection::convertDisconnectReason(u
|
|||||||
bool NetworkConnection::useDhcp = false;
|
bool NetworkConnection::useDhcp = false;
|
||||||
NetworkConnection::Status NetworkConnection::status = Status::NONE;
|
NetworkConnection::Status NetworkConnection::status = Status::NONE;
|
||||||
NetworkConnection::DisconnectReason NetworkConnection::disconnectReason = DisconnectReason::NONE;
|
NetworkConnection::DisconnectReason NetworkConnection::disconnectReason = DisconnectReason::NONE;
|
||||||
uint8_t NetworkConnection::rawDisconnectReason = 0;
|
uint8_t NetworkConnection::rawDisconnectReason = 0;
|
||||||
@@ -28,7 +28,7 @@ namespace NetworkUtils {
|
|||||||
static Status status;
|
static Status status;
|
||||||
static DisconnectReason disconnectReason;
|
static DisconnectReason disconnectReason;
|
||||||
static uint8_t rawDisconnectReason;
|
static uint8_t rawDisconnectReason;
|
||||||
|
|
||||||
static void setup(bool useDhcp);
|
static void setup(bool useDhcp);
|
||||||
static void setUseDhcp(bool value);
|
static void setUseDhcp(bool value);
|
||||||
static void reset();
|
static void reset();
|
||||||
@@ -44,4 +44,4 @@ namespace NetworkUtils {
|
|||||||
static DisconnectReason convertDisconnectReason(uint8_t reason);
|
static DisconnectReason convertDisconnectReason(uint8_t reason);
|
||||||
static bool useDhcp;
|
static bool useDhcp;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -183,7 +183,7 @@ namespace NetworkUtils {
|
|||||||
|
|
||||||
wifi_station_dhcpc_set_maxtry(5);
|
wifi_station_dhcpc_set_maxtry(5);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(ARDUINO_ARCH_ESP32) && ESP_ARDUINO_VERSION_MAJOR < 3
|
#if defined(ARDUINO_ARCH_ESP32) && ESP_ARDUINO_VERSION_MAJOR < 3
|
||||||
// Nothing. Because memory leaks when turn off WiFi on ESP32 SDK < 3.0.0
|
// Nothing. Because memory leaks when turn off WiFi on ESP32 SDK < 3.0.0
|
||||||
return true;
|
return true;
|
||||||
@@ -473,4 +473,4 @@ namespace NetworkUtils {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,224 @@
|
|||||||
|
#include <FS.h>
|
||||||
|
|
||||||
|
|
||||||
|
class DynamicPage : public RequestHandler {
|
||||||
|
public:
|
||||||
|
typedef std::function<bool(HTTPMethod, const String&)> CanHandleCallback;
|
||||||
|
typedef std::function<bool()> BeforeSendCallback;
|
||||||
|
typedef std::function<String(const char*)> TemplateCallback;
|
||||||
|
|
||||||
|
DynamicPage(const char* uri, FS* fs, const char* path, const char* cacheHeader = nullptr) {
|
||||||
|
this->uri = uri;
|
||||||
|
this->fs = fs;
|
||||||
|
this->path = path;
|
||||||
|
this->cacheHeader = cacheHeader;
|
||||||
|
}
|
||||||
|
|
||||||
|
DynamicPage* setCanHandleCallback(CanHandleCallback callback = nullptr) {
|
||||||
|
this->canHandleCallback = callback;
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
DynamicPage* setBeforeSendCallback(BeforeSendCallback callback = nullptr) {
|
||||||
|
this->beforeSendCallback = callback;
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
DynamicPage* setTemplateCallback(TemplateCallback callback = nullptr) {
|
||||||
|
this->templateCallback = callback;
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(ARDUINO_ARCH_ESP32)
|
||||||
|
bool canHandle(WebServer &server, HTTPMethod method, const String &uri) override {
|
||||||
|
return this->canHandle(method, uri);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
bool canHandle(HTTPMethod method, const String& uri) override {
|
||||||
|
return uri.equals(this->uri) && (!this->canHandleCallback || this->canHandleCallback(method, uri));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool handle(WebServer& server, HTTPMethod method, const String& uri) override {
|
||||||
|
if (!this->canHandle(method, uri)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this->beforeSendCallback && !this->beforeSendCallback()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
File file = this->fs->open(this->path, "r");
|
||||||
|
if (!file) {
|
||||||
|
return false;
|
||||||
|
|
||||||
|
} else if (file.isDirectory()) {
|
||||||
|
file.close();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this->cacheHeader != nullptr) {
|
||||||
|
server.sendHeader(F("Cache-Control"), this->cacheHeader);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef ARDUINO_ARCH_ESP8266
|
||||||
|
if (!server.chunkedResponseModeStart(200, F("text/html"))) {
|
||||||
|
server.send(505, F("text/html"), F("HTTP1.1 required"));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
server.setContentLength(CONTENT_LENGTH_UNKNOWN);
|
||||||
|
server.send(200, "text/html", emptyString);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
uint8_t* argStartPos = nullptr;
|
||||||
|
uint8_t* argEndPos = nullptr;
|
||||||
|
uint8_t argName[16];
|
||||||
|
size_t sizeArgName = 0;
|
||||||
|
bool argNameProcess = false;
|
||||||
|
while (file.available()) {
|
||||||
|
uint8_t buf[64];
|
||||||
|
size_t length = file.read(buf, sizeof(buf));
|
||||||
|
size_t offset = 0;
|
||||||
|
|
||||||
|
if (argNameProcess) {
|
||||||
|
argEndPos = (uint8_t*) memchr(buf, '}', length);
|
||||||
|
|
||||||
|
if (argEndPos != nullptr) {
|
||||||
|
size_t fullSizeArgName = sizeArgName + (argEndPos - buf);
|
||||||
|
if (fullSizeArgName < sizeof(argName)) {
|
||||||
|
// copy full arg name
|
||||||
|
if (argEndPos - buf > 0) {
|
||||||
|
memcpy(argName + sizeArgName, buf, argEndPos - buf);
|
||||||
|
}
|
||||||
|
argName[fullSizeArgName] = '\0';
|
||||||
|
|
||||||
|
// send arg value
|
||||||
|
String argValue = this->templateCallback((const char*) argName);
|
||||||
|
if (argValue.length()) {
|
||||||
|
server.sendContent(argValue.c_str());
|
||||||
|
|
||||||
|
} else if (fullSizeArgName > 0) {
|
||||||
|
server.sendContent("{");
|
||||||
|
server.sendContent((const char*) argName);
|
||||||
|
server.sendContent("}");
|
||||||
|
}
|
||||||
|
|
||||||
|
offset = size_t(argEndPos - buf + 1);
|
||||||
|
sizeArgName = 0;
|
||||||
|
argNameProcess = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (argNameProcess) {
|
||||||
|
server.sendContent("{");
|
||||||
|
|
||||||
|
if (sizeArgName > 0) {
|
||||||
|
argName[sizeArgName] = '\0';
|
||||||
|
server.sendContent((const char*) argName);
|
||||||
|
}
|
||||||
|
|
||||||
|
argNameProcess = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
do {
|
||||||
|
uint8_t* currentBuf = buf + offset;
|
||||||
|
size_t currentLength = length - offset;
|
||||||
|
|
||||||
|
argStartPos = (uint8_t*) memchr(currentBuf, '{', currentLength);
|
||||||
|
|
||||||
|
// send all content
|
||||||
|
if (argStartPos == nullptr) {
|
||||||
|
if (currentLength > 0) {
|
||||||
|
server.sendContent((const char*) currentBuf, currentLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
argEndPos = (uint8_t*) memchr(argStartPos, '}', length - (argStartPos - buf));
|
||||||
|
if (argEndPos != nullptr) {
|
||||||
|
sizeArgName = argEndPos - argStartPos - 1;
|
||||||
|
|
||||||
|
// send all content if arg len > space
|
||||||
|
if (sizeArgName >= sizeof(argName)) {
|
||||||
|
if (currentLength > 0) {
|
||||||
|
server.sendContent((const char*) currentBuf, currentLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// arg name
|
||||||
|
memcpy(argName, argStartPos + 1, sizeArgName);
|
||||||
|
argName[sizeArgName] = '\0';
|
||||||
|
|
||||||
|
// send arg value
|
||||||
|
String argValue = this->templateCallback((const char*) argName);
|
||||||
|
if (argValue.length()) {
|
||||||
|
// send content before var
|
||||||
|
if (argStartPos - buf > 0) {
|
||||||
|
server.sendContent((const char*) currentBuf, argStartPos - buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
server.sendContent(argValue.c_str());
|
||||||
|
|
||||||
|
} else {
|
||||||
|
server.sendContent((const char*) currentBuf, argEndPos - currentBuf + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
offset = size_t(argEndPos - currentBuf + 1);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
sizeArgName = length - size_t(argStartPos - currentBuf) - 1;
|
||||||
|
|
||||||
|
// send all content if arg len > space
|
||||||
|
if (sizeArgName >= sizeof(argName)) {
|
||||||
|
if (currentLength) {
|
||||||
|
server.sendContent((const char*) currentBuf, currentLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// send content before var
|
||||||
|
if (argStartPos - buf > 0) {
|
||||||
|
server.sendContent((const char*) currentBuf, argStartPos - buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
// copy arg name chunk
|
||||||
|
if (sizeArgName > 0) {
|
||||||
|
memcpy(argName, argStartPos + 1, sizeArgName);
|
||||||
|
}
|
||||||
|
|
||||||
|
argNameProcess = true;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} while(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
file.close();
|
||||||
|
|
||||||
|
#ifdef ARDUINO_ARCH_ESP8266
|
||||||
|
server.chunkedResponseFinalize();
|
||||||
|
#else
|
||||||
|
server.sendContent(emptyString);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
FS* fs = nullptr;
|
||||||
|
CanHandleCallback canHandleCallback;
|
||||||
|
BeforeSendCallback beforeSendCallback;
|
||||||
|
TemplateCallback templateCallback;
|
||||||
|
const char* uri = nullptr;
|
||||||
|
const char* path = nullptr;
|
||||||
|
const char* cacheHeader = nullptr;
|
||||||
|
};
|
||||||
@@ -7,7 +7,7 @@ class StaticPage : public RequestHandler {
|
|||||||
public:
|
public:
|
||||||
typedef std::function<bool(HTTPMethod, const String&)> CanHandleCallback;
|
typedef std::function<bool(HTTPMethod, const String&)> CanHandleCallback;
|
||||||
typedef std::function<bool()> BeforeSendCallback;
|
typedef std::function<bool()> BeforeSendCallback;
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
StaticPage(const char* uri, FS* fs, T path, const char* cacheHeader = nullptr) {
|
StaticPage(const char* uri, FS* fs, T path, const char* cacheHeader = nullptr) {
|
||||||
this->uri = uri;
|
this->uri = uri;
|
||||||
@@ -84,7 +84,7 @@ public:
|
|||||||
if (server._eTagEnabled && !this->eTag.isEmpty()) {
|
if (server._eTagEnabled && !this->eTag.isEmpty()) {
|
||||||
server.sendHeader(F("ETag"), this->eTag);
|
server.sendHeader(F("ETag"), this->eTag);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(ARDUINO_ARCH_ESP8266)
|
#if defined(ARDUINO_ARCH_ESP8266)
|
||||||
server.streamFile(file, F("text/html"), method);
|
server.streamFile(file, F("text/html"), method);
|
||||||
#else
|
#else
|
||||||
@@ -102,4 +102,4 @@ protected:
|
|||||||
const char* uri = nullptr;
|
const char* uri = nullptr;
|
||||||
String path;
|
String path;
|
||||||
const char* cacheHeader = nullptr;
|
const char* cacheHeader = nullptr;
|
||||||
};
|
};
|
||||||
@@ -28,14 +28,14 @@ public:
|
|||||||
|
|
||||||
typedef std::function<bool(AsyncWebServerRequest *request, UpgradeType)> BeforeUpgradeCallback;
|
typedef std::function<bool(AsyncWebServerRequest *request, UpgradeType)> BeforeUpgradeCallback;
|
||||||
typedef std::function<void(AsyncWebServerRequest *request, const UpgradeResult&, const UpgradeResult&)> AfterUpgradeCallback;
|
typedef std::function<void(AsyncWebServerRequest *request, const UpgradeResult&, const UpgradeResult&)> AfterUpgradeCallback;
|
||||||
|
|
||||||
|
UpgradeHandler(AsyncURIMatcher uri) : uri(uri) {}
|
||||||
|
|
||||||
explicit UpgradeHandler(AsyncURIMatcher uri) : uri(uri) {}
|
bool canHandle(AsyncWebServerRequest *request) const override final {
|
||||||
|
|
||||||
bool canHandle(AsyncWebServerRequest *request) const final {
|
|
||||||
if (!request->isHTTP()) {
|
if (!request->isHTTP()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return this->uri.matches(request);
|
return this->uri.matches(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -51,7 +51,7 @@ public:
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
void handleRequest(AsyncWebServerRequest *request) final {
|
void handleRequest(AsyncWebServerRequest *request) override final {
|
||||||
if (this->afterUpgradeCallback) {
|
if (this->afterUpgradeCallback) {
|
||||||
this->afterUpgradeCallback(request, this->firmwareResult, this->filesystemResult);
|
this->afterUpgradeCallback(request, this->firmwareResult, this->filesystemResult);
|
||||||
}
|
}
|
||||||
@@ -63,7 +63,7 @@ public:
|
|||||||
this->filesystemResult.error.clear();
|
this->filesystemResult.error.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void handleUpload(AsyncWebServerRequest *request, const String &fileName, size_t index, uint8_t *data, size_t dataLength, bool isFinal) final {
|
void handleUpload(AsyncWebServerRequest *request, const String &fileName, size_t index, uint8_t *data, size_t dataLength, bool isFinal) override final {
|
||||||
UpgradeResult* result = nullptr;
|
UpgradeResult* result = nullptr;
|
||||||
|
|
||||||
if (!request->hasParam(asyncsrv::T_name, true, true)) {
|
if (!request->hasParam(asyncsrv::T_name, true, true)) {
|
||||||
@@ -123,7 +123,7 @@ public:
|
|||||||
bool begin = false;
|
bool begin = false;
|
||||||
if (result->type == UpgradeType::FIRMWARE) {
|
if (result->type == UpgradeType::FIRMWARE) {
|
||||||
begin = Update.begin(UPDATE_SIZE_UNKNOWN, U_FLASH);
|
begin = Update.begin(UPDATE_SIZE_UNKNOWN, U_FLASH);
|
||||||
|
|
||||||
} else if (result->type == UpgradeType::FILESYSTEM) {
|
} else if (result->type == UpgradeType::FILESYSTEM) {
|
||||||
begin = Update.begin(UPDATE_SIZE_UNKNOWN, U_SPIFFS);
|
begin = Update.begin(UPDATE_SIZE_UNKNOWN, U_SPIFFS);
|
||||||
}
|
}
|
||||||
@@ -135,10 +135,10 @@ public:
|
|||||||
Log.serrorln(FPSTR(L_PORTAL_OTA), "File '%s', on start: %s", fileName.c_str(), result->error.c_str());
|
Log.serrorln(FPSTR(L_PORTAL_OTA), "File '%s', on start: %s", fileName.c_str(), result->error.c_str());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Log.sinfoln(FPSTR(L_PORTAL_OTA), "File '%s', started", fileName.c_str());
|
Log.sinfoln(FPSTR(L_PORTAL_OTA), "File '%s', started", fileName.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dataLength) {
|
if (dataLength) {
|
||||||
if (Update.write(data, dataLength) != dataLength) {
|
if (Update.write(data, dataLength) != dataLength) {
|
||||||
Update.end(false);
|
Update.end(false);
|
||||||
@@ -154,7 +154,7 @@ public:
|
|||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
result->progress += dataLength;
|
result->progress += dataLength;
|
||||||
Log.sinfoln(
|
Log.sinfoln(
|
||||||
FPSTR(L_PORTAL_OTA), "File '%s', write %d bytes, %d of %d bytes",
|
FPSTR(L_PORTAL_OTA), "File '%s', write %d bytes, %d of %d bytes",
|
||||||
@@ -179,7 +179,7 @@ public:
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isFinal) {
|
if (isFinal) {
|
||||||
if (!Update.end(true)) {
|
if (!Update.end(true)) {
|
||||||
result->status = UpgradeStatus::ERROR_ON_FINISH;
|
result->status = UpgradeStatus::ERROR_ON_FINISH;
|
||||||
@@ -194,7 +194,7 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isRequestHandlerTrivial() const final {
|
bool isRequestHandlerTrivial() const override final {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -205,4 +205,4 @@ protected:
|
|||||||
|
|
||||||
UpgradeResult firmwareResult{UpgradeType::FIRMWARE, UpgradeStatus::NONE};
|
UpgradeResult firmwareResult{UpgradeType::FIRMWARE, UpgradeStatus::NONE};
|
||||||
UpgradeResult filesystemResult{UpgradeType::FILESYSTEM, UpgradeStatus::NONE};
|
UpgradeResult filesystemResult{UpgradeType::FILESYSTEM, UpgradeStatus::NONE};
|
||||||
};
|
};
|
||||||
+6
-6
@@ -35,9 +35,9 @@ namespace CrashRecorder {
|
|||||||
} ext_t;
|
} ext_t;
|
||||||
|
|
||||||
|
|
||||||
__NOINIT_ATTR volatile static backtrace_t backtrace; // NOLINT
|
__NOINIT_ATTR volatile static backtrace_t backtrace;
|
||||||
__NOINIT_ATTR volatile static epc_t epc; // NOLINT
|
__NOINIT_ATTR volatile static epc_t epc;
|
||||||
__NOINIT_ATTR volatile static ext_t ext; // NOLINT
|
__NOINIT_ATTR volatile static ext_t ext;
|
||||||
|
|
||||||
uint8_t backtraceMaxLength = sizeof(backtrace.data) / sizeof(*backtrace.data);
|
uint8_t backtraceMaxLength = sizeof(backtrace.data) / sizeof(*backtrace.data);
|
||||||
uint8_t epcMaxLength = sizeof(epc.data) / sizeof(*epc.data);
|
uint8_t epcMaxLength = sizeof(epc.data) / sizeof(*epc.data);
|
||||||
@@ -70,7 +70,7 @@ namespace CrashRecorder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void init() {
|
void init() {
|
||||||
if (backtrace.length > backtraceMaxLength) {
|
if (backtrace.length > backtraceMaxLength) {
|
||||||
backtrace.length = 0;
|
backtrace.length = 0;
|
||||||
@@ -98,7 +98,7 @@ extern "C" void custom_crash_callback(struct rst_info *info, uint32_t stack, uin
|
|||||||
CrashRecorder::backtrace.continues = false;
|
CrashRecorder::backtrace.continues = false;
|
||||||
uint32_t value;
|
uint32_t value;
|
||||||
for (uint32_t i = stack; i < stack_end; i += 4) {
|
for (uint32_t i = stack; i < stack_end; i += 4) {
|
||||||
value = *((uint32_t*) i); // NOLINT
|
value = *((uint32_t*) i);
|
||||||
|
|
||||||
// keep only addresses in code area
|
// keep only addresses in code area
|
||||||
if ((value >= 0x40000000) && (value < 0x40300000)) {
|
if ((value >= 0x40000000) && (value < 0x40300000)) {
|
||||||
@@ -129,4 +129,4 @@ extern "C" void custom_crash_callback(struct rst_info *info, uint32_t stack, uin
|
|||||||
|
|
||||||
CrashRecorder::epc.length = _length;
|
CrashRecorder::epc.length = _length;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
+25
-25
@@ -45,7 +45,7 @@ public:
|
|||||||
doc[FPSTR(HA_MIN)] = -99;
|
doc[FPSTR(HA_MIN)] = -99;
|
||||||
doc[FPSTR(HA_MAX)] = 99;
|
doc[FPSTR(HA_MAX)] = 99;
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (unit == UnitSystem::IMPERIAL) {
|
} else if (unit == UnitSystem::IMPERIAL) {
|
||||||
doc[FPSTR(HA_UNIT_OF_MEASUREMENT)] = FPSTR(HA_UNIT_OF_MEASUREMENT_F);
|
doc[FPSTR(HA_UNIT_OF_MEASUREMENT)] = FPSTR(HA_UNIT_OF_MEASUREMENT_F);
|
||||||
|
|
||||||
@@ -60,7 +60,7 @@ public:
|
|||||||
doc[FPSTR(HA_DEVICE_CLASS)] = F("volume_flow_rate");
|
doc[FPSTR(HA_DEVICE_CLASS)] = F("volume_flow_rate");
|
||||||
if (unit == UnitSystem::METRIC) {
|
if (unit == UnitSystem::METRIC) {
|
||||||
doc[FPSTR(HA_UNIT_OF_MEASUREMENT)] = FPSTR(HA_UNIT_OF_MEASUREMENT_L_MIN);
|
doc[FPSTR(HA_UNIT_OF_MEASUREMENT)] = FPSTR(HA_UNIT_OF_MEASUREMENT_L_MIN);
|
||||||
|
|
||||||
} else if (unit == UnitSystem::IMPERIAL) {
|
} else if (unit == UnitSystem::IMPERIAL) {
|
||||||
doc[FPSTR(HA_UNIT_OF_MEASUREMENT)] = FPSTR(HA_UNIT_OF_MEASUREMENT_GAL_MIN);
|
doc[FPSTR(HA_UNIT_OF_MEASUREMENT)] = FPSTR(HA_UNIT_OF_MEASUREMENT_GAL_MIN);
|
||||||
}
|
}
|
||||||
@@ -110,19 +110,19 @@ public:
|
|||||||
case Sensors::Purpose::OUTDOOR_TEMP:
|
case Sensors::Purpose::OUTDOOR_TEMP:
|
||||||
doc[FPSTR(HA_ICON)] = F("mdi:home-thermometer-outline");
|
doc[FPSTR(HA_ICON)] = F("mdi:home-thermometer-outline");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Sensors::Purpose::INDOOR_TEMP:
|
case Sensors::Purpose::INDOOR_TEMP:
|
||||||
doc[FPSTR(HA_ICON)] = F("mdi:home-thermometer");
|
doc[FPSTR(HA_ICON)] = F("mdi:home-thermometer");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Sensors::Purpose::HEATING_TEMP:
|
case Sensors::Purpose::HEATING_TEMP:
|
||||||
doc[FPSTR(HA_ICON)] = F("mdi:radiator");
|
doc[FPSTR(HA_ICON)] = F("mdi:radiator");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Sensors::Purpose::HEATING_RETURN_TEMP:
|
case Sensors::Purpose::HEATING_RETURN_TEMP:
|
||||||
doc[FPSTR(HA_ICON)] = F("mdi:heating-coil");
|
doc[FPSTR(HA_ICON)] = F("mdi:heating-coil");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Sensors::Purpose::DHW_TEMP:
|
case Sensors::Purpose::DHW_TEMP:
|
||||||
doc[FPSTR(HA_ICON)] = F("mdi:faucet");
|
doc[FPSTR(HA_ICON)] = F("mdi:faucet");
|
||||||
break;
|
break;
|
||||||
@@ -130,7 +130,7 @@ public:
|
|||||||
case Sensors::Purpose::DHW_RETURN_TEMP:
|
case Sensors::Purpose::DHW_RETURN_TEMP:
|
||||||
doc[FPSTR(HA_ICON)] = F("mdi:heating-coil");
|
doc[FPSTR(HA_ICON)] = F("mdi:heating-coil");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Sensors::Purpose::EXHAUST_TEMP:
|
case Sensors::Purpose::EXHAUST_TEMP:
|
||||||
doc[FPSTR(HA_ICON)] = F("mdi:smoke");
|
doc[FPSTR(HA_ICON)] = F("mdi:smoke");
|
||||||
break;
|
break;
|
||||||
@@ -193,7 +193,7 @@ public:
|
|||||||
doc[FPSTR(HA_DEVICE_CLASS)] = FPSTR(S_TEMPERATURE);
|
doc[FPSTR(HA_DEVICE_CLASS)] = FPSTR(S_TEMPERATURE);
|
||||||
if (unit == UnitSystem::METRIC) {
|
if (unit == UnitSystem::METRIC) {
|
||||||
doc[FPSTR(HA_UNIT_OF_MEASUREMENT)] = FPSTR(HA_UNIT_OF_MEASUREMENT_C);
|
doc[FPSTR(HA_UNIT_OF_MEASUREMENT)] = FPSTR(HA_UNIT_OF_MEASUREMENT_C);
|
||||||
|
|
||||||
} else if (unit == UnitSystem::IMPERIAL) {
|
} else if (unit == UnitSystem::IMPERIAL) {
|
||||||
doc[FPSTR(HA_UNIT_OF_MEASUREMENT)] = FPSTR(HA_UNIT_OF_MEASUREMENT_F);
|
doc[FPSTR(HA_UNIT_OF_MEASUREMENT)] = FPSTR(HA_UNIT_OF_MEASUREMENT_F);
|
||||||
}
|
}
|
||||||
@@ -214,7 +214,7 @@ public:
|
|||||||
case Sensors::ValueType::BATTERY:
|
case Sensors::ValueType::BATTERY:
|
||||||
Sensors::makeObjectIdWithSuffix(objId, sSensor.name, FPSTR(S_BATTERY));
|
Sensors::makeObjectIdWithSuffix(objId, sSensor.name, FPSTR(S_BATTERY));
|
||||||
sName += F(" battery");
|
sName += F(" battery");
|
||||||
|
|
||||||
doc[FPSTR(HA_DEVICE_CLASS)] = FPSTR(S_BATTERY);
|
doc[FPSTR(HA_DEVICE_CLASS)] = FPSTR(S_BATTERY);
|
||||||
doc[FPSTR(HA_ENTITY_CATEGORY)] = FPSTR(HA_ENTITY_CATEGORY_DIAGNOSTIC);
|
doc[FPSTR(HA_ENTITY_CATEGORY)] = FPSTR(HA_ENTITY_CATEGORY_DIAGNOSTIC);
|
||||||
doc[FPSTR(HA_UNIT_OF_MEASUREMENT)] = FPSTR(HA_UNIT_OF_MEASUREMENT_PERCENT);
|
doc[FPSTR(HA_UNIT_OF_MEASUREMENT)] = FPSTR(HA_UNIT_OF_MEASUREMENT_PERCENT);
|
||||||
@@ -225,7 +225,7 @@ public:
|
|||||||
case Sensors::ValueType::RSSI:
|
case Sensors::ValueType::RSSI:
|
||||||
Sensors::makeObjectIdWithSuffix(objId, sSensor.name, FPSTR(S_RSSI));
|
Sensors::makeObjectIdWithSuffix(objId, sSensor.name, FPSTR(S_RSSI));
|
||||||
sName += F(" RSSI");
|
sName += F(" RSSI");
|
||||||
|
|
||||||
doc[FPSTR(HA_DEVICE_CLASS)] = F("signal_strength");
|
doc[FPSTR(HA_DEVICE_CLASS)] = F("signal_strength");
|
||||||
doc[FPSTR(HA_ENTITY_CATEGORY)] = FPSTR(HA_ENTITY_CATEGORY_DIAGNOSTIC);
|
doc[FPSTR(HA_ENTITY_CATEGORY)] = FPSTR(HA_ENTITY_CATEGORY_DIAGNOSTIC);
|
||||||
doc[FPSTR(HA_UNIT_OF_MEASUREMENT)] = F("dBm");
|
doc[FPSTR(HA_UNIT_OF_MEASUREMENT)] = F("dBm");
|
||||||
@@ -264,8 +264,8 @@ public:
|
|||||||
// object id's
|
// object id's
|
||||||
doc[FPSTR(HA_UNIQUE_ID)] = this->getUniqueIdWithPrefix(objId.c_str());
|
doc[FPSTR(HA_UNIQUE_ID)] = this->getUniqueIdWithPrefix(objId.c_str());
|
||||||
doc[FPSTR(HA_DEFAULT_ENTITY_ID)] = this->getEntityIdWithPrefix(
|
doc[FPSTR(HA_DEFAULT_ENTITY_ID)] = this->getEntityIdWithPrefix(
|
||||||
sSensor.type == Sensors::Type::MANUAL
|
sSensor.type == Sensors::Type::MANUAL
|
||||||
? FPSTR(HA_ENTITY_NUMBER)
|
? FPSTR(HA_ENTITY_NUMBER)
|
||||||
: FPSTR(HA_ENTITY_SENSOR),
|
: FPSTR(HA_ENTITY_SENSOR),
|
||||||
objId.c_str()
|
objId.c_str()
|
||||||
);
|
);
|
||||||
@@ -346,7 +346,7 @@ public:
|
|||||||
|
|
||||||
doc[FPSTR(HA_NAME)] = sName;
|
doc[FPSTR(HA_NAME)] = sName;
|
||||||
}
|
}
|
||||||
|
|
||||||
const String& configTopic = this->makeConfigTopic(FPSTR(HA_ENTITY_BINARY_SENSOR), objId.c_str());
|
const String& configTopic = this->makeConfigTopic(FPSTR(HA_ENTITY_BINARY_SENSOR), objId.c_str());
|
||||||
objId.clear();
|
objId.clear();
|
||||||
|
|
||||||
@@ -393,7 +393,7 @@ public:
|
|||||||
|
|
||||||
doc[FPSTR(HA_NAME)] = sName;
|
doc[FPSTR(HA_NAME)] = sName;
|
||||||
}
|
}
|
||||||
|
|
||||||
const String& configTopic = this->makeConfigTopic(FPSTR(HA_ENTITY_SENSOR), objId.c_str());
|
const String& configTopic = this->makeConfigTopic(FPSTR(HA_ENTITY_SENSOR), objId.c_str());
|
||||||
objId.clear();
|
objId.clear();
|
||||||
|
|
||||||
@@ -477,7 +477,7 @@ public:
|
|||||||
|
|
||||||
if (unit == UnitSystem::METRIC) {
|
if (unit == UnitSystem::METRIC) {
|
||||||
doc[FPSTR(HA_UNIT_OF_MEASUREMENT)] = FPSTR(HA_UNIT_OF_MEASUREMENT_C);
|
doc[FPSTR(HA_UNIT_OF_MEASUREMENT)] = FPSTR(HA_UNIT_OF_MEASUREMENT_C);
|
||||||
|
|
||||||
} else if (unit == UnitSystem::IMPERIAL) {
|
} else if (unit == UnitSystem::IMPERIAL) {
|
||||||
doc[FPSTR(HA_UNIT_OF_MEASUREMENT)] = FPSTR(HA_UNIT_OF_MEASUREMENT_F);
|
doc[FPSTR(HA_UNIT_OF_MEASUREMENT)] = FPSTR(HA_UNIT_OF_MEASUREMENT_F);
|
||||||
}
|
}
|
||||||
@@ -535,7 +535,7 @@ public:
|
|||||||
doc[FPSTR(HA_UNIT_OF_MEASUREMENT)] = FPSTR(HA_UNIT_OF_MEASUREMENT_C);
|
doc[FPSTR(HA_UNIT_OF_MEASUREMENT)] = FPSTR(HA_UNIT_OF_MEASUREMENT_C);
|
||||||
doc[FPSTR(HA_MIN)] = 0;
|
doc[FPSTR(HA_MIN)] = 0;
|
||||||
doc[FPSTR(HA_MAX)] = 99;
|
doc[FPSTR(HA_MAX)] = 99;
|
||||||
|
|
||||||
} else if (unit == UnitSystem::IMPERIAL) {
|
} else if (unit == UnitSystem::IMPERIAL) {
|
||||||
doc[FPSTR(HA_UNIT_OF_MEASUREMENT)] = FPSTR(HA_UNIT_OF_MEASUREMENT_F);
|
doc[FPSTR(HA_UNIT_OF_MEASUREMENT)] = FPSTR(HA_UNIT_OF_MEASUREMENT_F);
|
||||||
doc[FPSTR(HA_MIN)] = 32;
|
doc[FPSTR(HA_MIN)] = 32;
|
||||||
@@ -569,7 +569,7 @@ public:
|
|||||||
doc[FPSTR(HA_UNIT_OF_MEASUREMENT)] = FPSTR(HA_UNIT_OF_MEASUREMENT_C);
|
doc[FPSTR(HA_UNIT_OF_MEASUREMENT)] = FPSTR(HA_UNIT_OF_MEASUREMENT_C);
|
||||||
doc[FPSTR(HA_MIN)] = 1;
|
doc[FPSTR(HA_MIN)] = 1;
|
||||||
doc[FPSTR(HA_MAX)] = 100;
|
doc[FPSTR(HA_MAX)] = 100;
|
||||||
|
|
||||||
} else if (unit == UnitSystem::IMPERIAL) {
|
} else if (unit == UnitSystem::IMPERIAL) {
|
||||||
doc[FPSTR(HA_UNIT_OF_MEASUREMENT)] = FPSTR(HA_UNIT_OF_MEASUREMENT_F);
|
doc[FPSTR(HA_UNIT_OF_MEASUREMENT)] = FPSTR(HA_UNIT_OF_MEASUREMENT_F);
|
||||||
doc[FPSTR(HA_MIN)] = 33;
|
doc[FPSTR(HA_MIN)] = 33;
|
||||||
@@ -604,7 +604,7 @@ public:
|
|||||||
doc[FPSTR(HA_UNIT_OF_MEASUREMENT)] = FPSTR(HA_UNIT_OF_MEASUREMENT_C);
|
doc[FPSTR(HA_UNIT_OF_MEASUREMENT)] = FPSTR(HA_UNIT_OF_MEASUREMENT_C);
|
||||||
doc[FPSTR(HA_MIN)] = 0;
|
doc[FPSTR(HA_MIN)] = 0;
|
||||||
doc[FPSTR(HA_MAX)] = 99;
|
doc[FPSTR(HA_MAX)] = 99;
|
||||||
|
|
||||||
} else if (unit == UnitSystem::IMPERIAL) {
|
} else if (unit == UnitSystem::IMPERIAL) {
|
||||||
doc[FPSTR(HA_UNIT_OF_MEASUREMENT)] = FPSTR(HA_UNIT_OF_MEASUREMENT_F);
|
doc[FPSTR(HA_UNIT_OF_MEASUREMENT)] = FPSTR(HA_UNIT_OF_MEASUREMENT_F);
|
||||||
doc[FPSTR(HA_MIN)] = 32;
|
doc[FPSTR(HA_MIN)] = 32;
|
||||||
@@ -638,7 +638,7 @@ public:
|
|||||||
doc[FPSTR(HA_UNIT_OF_MEASUREMENT)] = FPSTR(HA_UNIT_OF_MEASUREMENT_C);
|
doc[FPSTR(HA_UNIT_OF_MEASUREMENT)] = FPSTR(HA_UNIT_OF_MEASUREMENT_C);
|
||||||
doc[FPSTR(HA_MIN)] = 1;
|
doc[FPSTR(HA_MIN)] = 1;
|
||||||
doc[FPSTR(HA_MAX)] = 100;
|
doc[FPSTR(HA_MAX)] = 100;
|
||||||
|
|
||||||
} else if (unit == UnitSystem::IMPERIAL) {
|
} else if (unit == UnitSystem::IMPERIAL) {
|
||||||
doc[FPSTR(HA_UNIT_OF_MEASUREMENT)] = FPSTR(HA_UNIT_OF_MEASUREMENT_F);
|
doc[FPSTR(HA_UNIT_OF_MEASUREMENT)] = FPSTR(HA_UNIT_OF_MEASUREMENT_F);
|
||||||
doc[FPSTR(HA_MIN)] = 33;
|
doc[FPSTR(HA_MIN)] = 33;
|
||||||
@@ -789,7 +789,7 @@ public:
|
|||||||
doc[FPSTR(HA_UNIT_OF_MEASUREMENT)] = FPSTR(HA_UNIT_OF_MEASUREMENT_C);
|
doc[FPSTR(HA_UNIT_OF_MEASUREMENT)] = FPSTR(HA_UNIT_OF_MEASUREMENT_C);
|
||||||
doc[FPSTR(HA_MIN)] = -99;
|
doc[FPSTR(HA_MIN)] = -99;
|
||||||
doc[FPSTR(HA_MAX)] = 99;
|
doc[FPSTR(HA_MAX)] = 99;
|
||||||
|
|
||||||
} else if (unit == UnitSystem::IMPERIAL) {
|
} else if (unit == UnitSystem::IMPERIAL) {
|
||||||
doc[FPSTR(HA_UNIT_OF_MEASUREMENT)] = FPSTR(HA_UNIT_OF_MEASUREMENT_F);
|
doc[FPSTR(HA_UNIT_OF_MEASUREMENT)] = FPSTR(HA_UNIT_OF_MEASUREMENT_F);
|
||||||
doc[FPSTR(HA_MIN)] = -146;
|
doc[FPSTR(HA_MIN)] = -146;
|
||||||
@@ -823,7 +823,7 @@ public:
|
|||||||
doc[FPSTR(HA_UNIT_OF_MEASUREMENT)] = FPSTR(HA_UNIT_OF_MEASUREMENT_C);
|
doc[FPSTR(HA_UNIT_OF_MEASUREMENT)] = FPSTR(HA_UNIT_OF_MEASUREMENT_C);
|
||||||
doc[FPSTR(HA_MIN)] = 1;
|
doc[FPSTR(HA_MIN)] = 1;
|
||||||
doc[FPSTR(HA_MAX)] = 100;
|
doc[FPSTR(HA_MAX)] = 100;
|
||||||
|
|
||||||
} else if (unit == UnitSystem::IMPERIAL) {
|
} else if (unit == UnitSystem::IMPERIAL) {
|
||||||
doc[FPSTR(HA_UNIT_OF_MEASUREMENT)] = FPSTR(HA_UNIT_OF_MEASUREMENT_F);
|
doc[FPSTR(HA_UNIT_OF_MEASUREMENT)] = FPSTR(HA_UNIT_OF_MEASUREMENT_F);
|
||||||
doc[FPSTR(HA_MIN)] = 1;
|
doc[FPSTR(HA_MIN)] = 1;
|
||||||
@@ -1238,7 +1238,7 @@ public:
|
|||||||
|
|
||||||
if (unit == UnitSystem::METRIC) {
|
if (unit == UnitSystem::METRIC) {
|
||||||
doc[FPSTR(HA_TEMPERATURE_UNIT)] = "C";
|
doc[FPSTR(HA_TEMPERATURE_UNIT)] = "C";
|
||||||
|
|
||||||
} else if (unit == UnitSystem::IMPERIAL) {
|
} else if (unit == UnitSystem::IMPERIAL) {
|
||||||
doc[FPSTR(HA_TEMPERATURE_UNIT)] = "F";
|
doc[FPSTR(HA_TEMPERATURE_UNIT)] = "F";
|
||||||
}
|
}
|
||||||
@@ -1290,7 +1290,7 @@ public:
|
|||||||
|
|
||||||
if (unit == UnitSystem::METRIC) {
|
if (unit == UnitSystem::METRIC) {
|
||||||
doc[FPSTR(HA_TEMPERATURE_UNIT)] = "C";
|
doc[FPSTR(HA_TEMPERATURE_UNIT)] = "C";
|
||||||
|
|
||||||
} else if (unit == UnitSystem::IMPERIAL) {
|
} else if (unit == UnitSystem::IMPERIAL) {
|
||||||
doc[FPSTR(HA_TEMPERATURE_UNIT)] = "F";
|
doc[FPSTR(HA_TEMPERATURE_UNIT)] = "F";
|
||||||
}
|
}
|
||||||
@@ -1393,7 +1393,7 @@ public:
|
|||||||
bool deleteDhwState() {
|
bool deleteDhwState() {
|
||||||
return this->publish(this->makeConfigTopic(FPSTR(HA_ENTITY_BINARY_SENSOR), F("dhw")).c_str());
|
return this->publish(this->makeConfigTopic(FPSTR(HA_ENTITY_BINARY_SENSOR), F("dhw")).c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool deleteInputDhwTarget() {
|
bool deleteInputDhwTarget() {
|
||||||
return this->publish(this->makeConfigTopic(FPSTR(HA_ENTITY_NUMBER), F("dhw_target")).c_str());
|
return this->publish(this->makeConfigTopic(FPSTR(HA_ENTITY_NUMBER), F("dhw_target")).c_str());
|
||||||
}
|
}
|
||||||
@@ -1408,4 +1408,4 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
const char HaHelper::AVAILABILITY_OT_CONN[] = "{{ iif(value_json.slave.connected, 'online', 'offline') }}";
|
const char HaHelper::AVAILABILITY_OT_CONN[] = "{{ iif(value_json.slave.connected, 'online', 'offline') }}";
|
||||||
const char HaHelper::AVAILABILITY_SENSOR_CONN[] = "{{ iif(value_json.connected, 'online', 'offline') }}";
|
const char HaHelper::AVAILABILITY_SENSOR_CONN[] = "{{ iif(value_json.connected, 'online', 'offline') }}";
|
||||||
+23
-23
@@ -10,7 +10,7 @@ extern FileData fsNetworkSettings, fsSettings, fsSensorsSettings;
|
|||||||
|
|
||||||
class MainTask : public Task {
|
class MainTask : public Task {
|
||||||
public:
|
public:
|
||||||
explicit MainTask(bool _enabled = false, unsigned long _interval = 0) : Task(_enabled, _interval) {
|
MainTask(bool _enabled = false, unsigned long _interval = 0) : Task(_enabled, _interval) {
|
||||||
this->blinker = new Blinker();
|
this->blinker = new Blinker();
|
||||||
|
|
||||||
network->setDelayCallback([this](unsigned int time) {
|
network->setDelayCallback([this](unsigned int time) {
|
||||||
@@ -175,7 +175,7 @@ protected:
|
|||||||
this->cascadeControl();
|
this->cascadeControl();
|
||||||
this->externalPump();
|
this->externalPump();
|
||||||
this->miscRunned = millis();
|
this->miscRunned = millis();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -200,7 +200,7 @@ protected:
|
|||||||
minFreeHeapDiff = this->minFreeHeap - minFreeHeap;
|
minFreeHeapDiff = this->minFreeHeap - minFreeHeap;
|
||||||
this->minFreeHeap = minFreeHeap;
|
this->minFreeHeap = minFreeHeap;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t minMaxFreeBlockHeap = getMaxFreeBlockHeap(true);
|
size_t minMaxFreeBlockHeap = getMaxFreeBlockHeap(true);
|
||||||
size_t minMaxFreeBlockHeapDiff = 0;
|
size_t minMaxFreeBlockHeapDiff = 0;
|
||||||
if (minMaxFreeBlockHeap < this->minMaxFreeBlockHeap || this->minMaxFreeBlockHeap == 0) {
|
if (minMaxFreeBlockHeap < this->minMaxFreeBlockHeap || this->minMaxFreeBlockHeap == 0) {
|
||||||
@@ -229,7 +229,7 @@ protected:
|
|||||||
if (value < lowTemp) {
|
if (value < lowTemp) {
|
||||||
lowTemp = value;
|
lowTemp = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
availableSensors++;
|
availableSensors++;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -238,7 +238,7 @@ protected:
|
|||||||
if (value < lowTemp) {
|
if (value < lowTemp) {
|
||||||
lowTemp = value;
|
lowTemp = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
availableSensors++;
|
availableSensors++;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -253,7 +253,7 @@ protected:
|
|||||||
|
|
||||||
if (availableSensors) {
|
if (availableSensors) {
|
||||||
if (vars.master.heating.freezing) {
|
if (vars.master.heating.freezing) {
|
||||||
if (lowTemp - static_cast<float>(settings.heating.freezeProtection.highTemp) + 0.0001f >= 0.0f) {
|
if (lowTemp - (float) settings.heating.freezeProtection.highTemp + 0.0001f >= 0.0f) {
|
||||||
vars.master.heating.freezing = false;
|
vars.master.heating.freezing = false;
|
||||||
|
|
||||||
Log.sinfoln(
|
Log.sinfoln(
|
||||||
@@ -264,7 +264,7 @@ protected:
|
|||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
if (static_cast<float>(settings.heating.freezeProtection.lowTemp) - lowTemp + 0.0001f >= 0.0f) {
|
if ((float) settings.heating.freezeProtection.lowTemp - lowTemp + 0.0001f >= 0.0f) {
|
||||||
vars.master.heating.freezing = true;
|
vars.master.heating.freezing = true;
|
||||||
|
|
||||||
if (!settings.heating.enabled) {
|
if (!settings.heating.enabled) {
|
||||||
@@ -304,7 +304,7 @@ protected:
|
|||||||
if (!settings.equitherm.enabled && settings.pid.enabled) {
|
if (!settings.equitherm.enabled && settings.pid.enabled) {
|
||||||
emergencyFlags |= 0b00000010;
|
emergencyFlags |= 0b00000010;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (settings.opentherm.options.nativeOTC) {
|
if (settings.opentherm.options.nativeOTC) {
|
||||||
emergencyFlags |= 0b00000100;
|
emergencyFlags |= 0b00000100;
|
||||||
}
|
}
|
||||||
@@ -353,7 +353,7 @@ protected:
|
|||||||
if (configuredGpio != GPIO_IS_NOT_CONFIGURED) {
|
if (configuredGpio != GPIO_IS_NOT_CONFIGURED) {
|
||||||
digitalWrite(configuredGpio, LOW);
|
digitalWrite(configuredGpio, LOW);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GPIO_IS_VALID(settings.system.statusLedGpio)) {
|
if (GPIO_IS_VALID(settings.system.statusLedGpio)) {
|
||||||
configuredGpio = settings.system.statusLedGpio;
|
configuredGpio = settings.system.statusLedGpio;
|
||||||
pinMode(configuredGpio, OUTPUT);
|
pinMode(configuredGpio, OUTPUT);
|
||||||
@@ -437,7 +437,7 @@ protected:
|
|||||||
|
|
||||||
Log.sinfoln(FPSTR(L_CASCADE_INPUT), F("Deinitialized on GPIO %hhu"), configuredInputGpio);
|
Log.sinfoln(FPSTR(L_CASCADE_INPUT), F("Deinitialized on GPIO %hhu"), configuredInputGpio);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GPIO_IS_VALID(settings.cascadeControl.input.gpio)) {
|
if (GPIO_IS_VALID(settings.cascadeControl.input.gpio)) {
|
||||||
configuredInputGpio = settings.cascadeControl.input.gpio;
|
configuredInputGpio = settings.cascadeControl.input.gpio;
|
||||||
pinMode(configuredInputGpio, INPUT);
|
pinMode(configuredInputGpio, INPUT);
|
||||||
@@ -479,7 +479,7 @@ protected:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!settings.cascadeControl.input.enabled || configuredInputGpio == GPIO_IS_NOT_CONFIGURED) {
|
if (!settings.cascadeControl.input.enabled || configuredInputGpio == GPIO_IS_NOT_CONFIGURED) {
|
||||||
if (!vars.cascadeControl.input) {
|
if (!vars.cascadeControl.input) {
|
||||||
vars.cascadeControl.input = true;
|
vars.cascadeControl.input = true;
|
||||||
@@ -502,14 +502,14 @@ protected:
|
|||||||
|
|
||||||
Log.sinfoln(FPSTR(L_CASCADE_OUTPUT), F("Deinitialized on GPIO %hhu"), configuredOutputGpio);
|
Log.sinfoln(FPSTR(L_CASCADE_OUTPUT), F("Deinitialized on GPIO %hhu"), configuredOutputGpio);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GPIO_IS_VALID(settings.cascadeControl.output.gpio)) {
|
if (GPIO_IS_VALID(settings.cascadeControl.output.gpio)) {
|
||||||
configuredOutputGpio = settings.cascadeControl.output.gpio;
|
configuredOutputGpio = settings.cascadeControl.output.gpio;
|
||||||
pinMode(configuredOutputGpio, OUTPUT);
|
pinMode(configuredOutputGpio, OUTPUT);
|
||||||
digitalWrite(
|
digitalWrite(
|
||||||
configuredOutputGpio,
|
configuredOutputGpio,
|
||||||
settings.cascadeControl.output.invertState
|
settings.cascadeControl.output.invertState
|
||||||
? HIGH
|
? HIGH
|
||||||
: LOW
|
: LOW
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -538,7 +538,7 @@ protected:
|
|||||||
if (value != outputTempValue) {
|
if (value != outputTempValue) {
|
||||||
outputTempValue = value;
|
outputTempValue = value;
|
||||||
outputChangedTs = millis();
|
outputChangedTs = millis();
|
||||||
|
|
||||||
} else if (millis() - outputChangedTs >= settings.cascadeControl.output.thresholdTime * 1000u) {
|
} else if (millis() - outputChangedTs >= settings.cascadeControl.output.thresholdTime * 1000u) {
|
||||||
vars.cascadeControl.output = value;
|
vars.cascadeControl.output = value;
|
||||||
|
|
||||||
@@ -591,14 +591,14 @@ protected:
|
|||||||
if (configuredGpio != GPIO_IS_NOT_CONFIGURED) {
|
if (configuredGpio != GPIO_IS_NOT_CONFIGURED) {
|
||||||
digitalWrite(configuredGpio, LOW);
|
digitalWrite(configuredGpio, LOW);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GPIO_IS_VALID(settings.externalPump.gpio)) {
|
if (GPIO_IS_VALID(settings.externalPump.gpio)) {
|
||||||
configuredGpio = settings.externalPump.gpio;
|
configuredGpio = settings.externalPump.gpio;
|
||||||
pinMode(configuredGpio, OUTPUT);
|
pinMode(configuredGpio, OUTPUT);
|
||||||
digitalWrite(
|
digitalWrite(
|
||||||
configuredGpio,
|
configuredGpio,
|
||||||
settings.externalPump.invertState
|
settings.externalPump.invertState
|
||||||
? HIGH
|
? HIGH
|
||||||
: LOW
|
: LOW
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -625,13 +625,13 @@ protected:
|
|||||||
} else if (vars.master.heating.enabled && !this->heatingEnabled) {
|
} else if (vars.master.heating.enabled && !this->heatingEnabled) {
|
||||||
this->heatingEnabled = true;
|
this->heatingEnabled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!settings.externalPump.use) {
|
if (!settings.externalPump.use) {
|
||||||
if (vars.externalPump.state) {
|
if (vars.externalPump.state) {
|
||||||
digitalWrite(
|
digitalWrite(
|
||||||
configuredGpio,
|
configuredGpio,
|
||||||
settings.externalPump.invertState
|
settings.externalPump.invertState
|
||||||
? HIGH
|
? HIGH
|
||||||
: LOW
|
: LOW
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -649,7 +649,7 @@ protected:
|
|||||||
digitalWrite(
|
digitalWrite(
|
||||||
configuredGpio,
|
configuredGpio,
|
||||||
settings.externalPump.invertState
|
settings.externalPump.invertState
|
||||||
? HIGH
|
? HIGH
|
||||||
: LOW
|
: LOW
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -662,7 +662,7 @@ protected:
|
|||||||
digitalWrite(
|
digitalWrite(
|
||||||
configuredGpio,
|
configuredGpio,
|
||||||
settings.externalPump.invertState
|
settings.externalPump.invertState
|
||||||
? HIGH
|
? HIGH
|
||||||
: LOW
|
: LOW
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -683,7 +683,7 @@ protected:
|
|||||||
digitalWrite(
|
digitalWrite(
|
||||||
configuredGpio,
|
configuredGpio,
|
||||||
settings.externalPump.invertState
|
settings.externalPump.invertState
|
||||||
? LOW
|
? LOW
|
||||||
: HIGH
|
: HIGH
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -697,11 +697,11 @@ protected:
|
|||||||
digitalWrite(
|
digitalWrite(
|
||||||
configuredGpio,
|
configuredGpio,
|
||||||
settings.externalPump.invertState
|
settings.externalPump.invertState
|
||||||
? LOW
|
? LOW
|
||||||
: HIGH
|
: HIGH
|
||||||
);
|
);
|
||||||
|
|
||||||
Log.sinfoln(FPSTR(L_EXTPUMP), F("Enabled: anti stuck"));
|
Log.sinfoln(FPSTR(L_EXTPUMP), F("Enabled: anti stuck"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
+8
-8
@@ -8,7 +8,7 @@ extern FileData fsSettings;
|
|||||||
|
|
||||||
class MqttTask : public Task {
|
class MqttTask : public Task {
|
||||||
public:
|
public:
|
||||||
explicit MqttTask(bool _enabled = false, unsigned long _interval = 0) : Task(_enabled, _interval) {
|
MqttTask(bool _enabled = false, unsigned long _interval = 0) : Task(_enabled, _interval) {
|
||||||
this->wifiClient = new MqttWiFiClient();
|
this->wifiClient = new MqttWiFiClient();
|
||||||
this->client = new MqttClient(this->wifiClient);
|
this->client = new MqttClient(this->wifiClient);
|
||||||
this->writer = new MqttWriter(this->client, 256);
|
this->writer = new MqttWriter(this->client, 256);
|
||||||
@@ -42,7 +42,7 @@ public:
|
|||||||
this->onDisconnect();
|
this->onDisconnect();
|
||||||
this->connected = false;
|
this->connected = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Task::disable();
|
Task::disable();
|
||||||
|
|
||||||
Log.sinfoln(FPSTR(L_MQTT), F("Disabled"));
|
Log.sinfoln(FPSTR(L_MQTT), F("Disabled"));
|
||||||
@@ -96,7 +96,7 @@ protected:
|
|||||||
const char* getTaskName() override {
|
const char* getTaskName() override {
|
||||||
return "Mqtt";
|
return "Mqtt";
|
||||||
}
|
}
|
||||||
|
|
||||||
/*BaseType_t getTaskCore() override {
|
/*BaseType_t getTaskCore() override {
|
||||||
return 1;
|
return 1;
|
||||||
}*/
|
}*/
|
||||||
@@ -137,7 +137,7 @@ protected:
|
|||||||
for (size_t i = 0; i < length && this->client->available(); i++) {
|
for (size_t i = 0; i < length && this->client->available(); i++) {
|
||||||
payload[i] = this->client->read();
|
payload[i] = this->client->read();
|
||||||
}
|
}
|
||||||
|
|
||||||
this->onMessage(topic, payload, length);
|
this->onMessage(topic, payload, length);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -340,7 +340,7 @@ protected:
|
|||||||
this->haHelper->publishSignalQualityDynamicSensor(sSettings, false);
|
this->haHelper->publishSignalQualityDynamicSensor(sSettings, false);
|
||||||
this->haHelper->publishDynamicSensor(sSettings, Sensors::ValueType::TEMPERATURE, settings.system.unitSystem);
|
this->haHelper->publishDynamicSensor(sSettings, Sensors::ValueType::TEMPERATURE, settings.system.unitSystem);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
this->haHelper->publishDynamicSensor(sSettings, Sensors::ValueType::PRIMARY, settings.system.unitSystem);
|
this->haHelper->publishDynamicSensor(sSettings, Sensors::ValueType::PRIMARY, settings.system.unitSystem);
|
||||||
}
|
}
|
||||||
@@ -443,7 +443,7 @@ protected:
|
|||||||
} else if (payload[i] == 10) {
|
} else if (payload[i] == 10) {
|
||||||
Log.print(F("\r\n> "));
|
Log.print(F("\r\n> "));
|
||||||
} else {
|
} else {
|
||||||
Log.print(static_cast<char>(payload[i]));
|
Log.print((char) payload[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Log.print(F("\r\n\n"));
|
Log.print(F("\r\n\n"));
|
||||||
@@ -567,7 +567,7 @@ protected:
|
|||||||
this->haHelper->publishSignalQualityDynamicSensor(sSettings, false);
|
this->haHelper->publishSignalQualityDynamicSensor(sSettings, false);
|
||||||
this->haHelper->publishDynamicSensor(sSettings, Sensors::ValueType::TEMPERATURE, settings.system.unitSystem);
|
this->haHelper->publishDynamicSensor(sSettings, Sensors::ValueType::TEMPERATURE, settings.system.unitSystem);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
this->haHelper->publishDynamicSensor(sSettings, Sensors::ValueType::PRIMARY, settings.system.unitSystem);
|
this->haHelper->publishDynamicSensor(sSettings, Sensors::ValueType::PRIMARY, settings.system.unitSystem);
|
||||||
}
|
}
|
||||||
@@ -664,4 +664,4 @@ protected:
|
|||||||
|
|
||||||
return this->writer->publish(topic, doc, true);
|
return this->writer->publish(topic, doc, true);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
+38
-38
@@ -3,7 +3,7 @@ extern FileData fsSettings;
|
|||||||
|
|
||||||
class OpenThermTask : public Task {
|
class OpenThermTask : public Task {
|
||||||
public:
|
public:
|
||||||
explicit OpenThermTask(bool _enabled = false, unsigned long _interval = 0) : Task(_enabled, _interval) {}
|
OpenThermTask(bool _enabled = false, unsigned long _interval = 0) : Task(_enabled, _interval) {}
|
||||||
|
|
||||||
~OpenThermTask() {
|
~OpenThermTask() {
|
||||||
delete this->instance;
|
delete this->instance;
|
||||||
@@ -41,7 +41,7 @@ protected:
|
|||||||
uint32_t getTaskStackSize() override {
|
uint32_t getTaskStackSize() override {
|
||||||
return 7500;
|
return 7500;
|
||||||
}
|
}
|
||||||
|
|
||||||
BaseType_t getTaskCore() override {
|
BaseType_t getTaskCore() override {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -160,7 +160,7 @@ protected:
|
|||||||
if (this->configuredRxLedGpio != GPIO_IS_NOT_CONFIGURED) {
|
if (this->configuredRxLedGpio != GPIO_IS_NOT_CONFIGURED) {
|
||||||
digitalWrite(this->configuredRxLedGpio, LOW);
|
digitalWrite(this->configuredRxLedGpio, LOW);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GPIO_IS_VALID(settings.opentherm.rxLedGpio)) {
|
if (GPIO_IS_VALID(settings.opentherm.rxLedGpio)) {
|
||||||
this->configuredRxLedGpio = settings.opentherm.rxLedGpio;
|
this->configuredRxLedGpio = settings.opentherm.rxLedGpio;
|
||||||
pinMode(this->configuredRxLedGpio, OUTPUT);
|
pinMode(this->configuredRxLedGpio, OUTPUT);
|
||||||
@@ -178,8 +178,8 @@ protected:
|
|||||||
&& !vars.master.heating.overheat;
|
&& !vars.master.heating.overheat;
|
||||||
|
|
||||||
// DHW settings
|
// DHW settings
|
||||||
vars.master.dhw.enabled = settings.opentherm.options.dhwSupport
|
vars.master.dhw.enabled = settings.opentherm.options.dhwSupport
|
||||||
&& settings.dhw.enabled
|
&& settings.dhw.enabled
|
||||||
&& !vars.master.dhw.overheat;
|
&& !vars.master.dhw.overheat;
|
||||||
vars.master.dhw.targetTemp = settings.dhw.target;
|
vars.master.dhw.targetTemp = settings.dhw.target;
|
||||||
|
|
||||||
@@ -236,7 +236,7 @@ protected:
|
|||||||
F("Failed receive boiler status: %s"),
|
F("Failed receive boiler status: %s"),
|
||||||
CustomOpenTherm::statusToString(this->instance->getLastResponseStatus())
|
CustomOpenTherm::statusToString(this->instance->getLastResponseStatus())
|
||||||
);
|
);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
vars.slave.heating.active = CustomOpenTherm::isCentralHeatingActive(response);
|
vars.slave.heating.active = CustomOpenTherm::isCentralHeatingActive(response);
|
||||||
vars.slave.dhw.active = settings.opentherm.options.dhwSupport ? CustomOpenTherm::isHotWaterActive(response) : false;
|
vars.slave.dhw.active = settings.opentherm.options.dhwSupport ? CustomOpenTherm::isHotWaterActive(response) : false;
|
||||||
@@ -251,7 +251,7 @@ protected:
|
|||||||
} else if (vars.slave.diag.active) {
|
} else if (vars.slave.diag.active) {
|
||||||
vars.slave.diag.active = false;
|
vars.slave.diag.active = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Log.snoticeln(
|
Log.snoticeln(
|
||||||
FPSTR(L_OT), F("Received boiler status. Heating: %hhu; DHW: %hhu; flame: %hhu; cooling: %hhu; channel 2: %hhu; fault: %hhu; diag: %hhu"),
|
FPSTR(L_OT), F("Received boiler status. Heating: %hhu; DHW: %hhu; flame: %hhu; cooling: %hhu; channel 2: %hhu; fault: %hhu; diag: %hhu"),
|
||||||
vars.slave.heating.active, vars.slave.dhw.active,
|
vars.slave.heating.active, vars.slave.dhw.active,
|
||||||
@@ -270,15 +270,15 @@ protected:
|
|||||||
F("Connected, downtime: %lu s."),
|
F("Connected, downtime: %lu s."),
|
||||||
(millis() - this->disconnectedTime) / 1000
|
(millis() - this->disconnectedTime) / 1000
|
||||||
);
|
);
|
||||||
|
|
||||||
this->connectedTime = millis();
|
this->connectedTime = millis();
|
||||||
vars.slave.connected = true;
|
vars.slave.connected = true;
|
||||||
|
|
||||||
} else if (vars.slave.connected && millis() - this->lastSuccessResponse > 6325) {
|
} else if (vars.slave.connected && millis() - this->lastSuccessResponse > 6325) {
|
||||||
Log.swarningln(
|
Log.swarningln(
|
||||||
FPSTR(L_OT),
|
FPSTR(L_OT),
|
||||||
F("Disconnected, uptime: %lu s."),
|
F("Disconnected, uptime: %lu s."),
|
||||||
(millis() - this->connectedTime) / 1000
|
(millis() - this->connectedTime) / 1000
|
||||||
);
|
);
|
||||||
|
|
||||||
// Mark sensors as disconnected
|
// Mark sensors as disconnected
|
||||||
@@ -403,7 +403,7 @@ protected:
|
|||||||
FPSTR(L_OT), F("Received min modulation: %hhu%%, max power: %.2f kW"),
|
FPSTR(L_OT), F("Received min modulation: %hhu%%, max power: %.2f kW"),
|
||||||
vars.slave.modulation.min, vars.slave.power.max
|
vars.slave.modulation.min, vars.slave.power.max
|
||||||
);
|
);
|
||||||
|
|
||||||
if (settings.heating.maxModulation < vars.slave.modulation.min) {
|
if (settings.heating.maxModulation < vars.slave.modulation.min) {
|
||||||
settings.heating.maxModulation = vars.slave.modulation.min;
|
settings.heating.maxModulation = vars.slave.modulation.min;
|
||||||
fsSettings.update();
|
fsSettings.update();
|
||||||
@@ -519,7 +519,7 @@ protected:
|
|||||||
|
|
||||||
Log.swarningln(FPSTR(L_SETTINGS_HEATING), F("Updated max temp: %hhu"), settings.heating.maxTemp);
|
Log.swarningln(FPSTR(L_SETTINGS_HEATING), F("Updated max temp: %hhu"), settings.heating.maxTemp);
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
Log.swarningln(FPSTR(L_OT_HEATING), F("Failed receive min/max temp"));
|
Log.swarningln(FPSTR(L_OT_HEATING), F("Failed receive min/max temp"));
|
||||||
}
|
}
|
||||||
@@ -542,7 +542,7 @@ protected:
|
|||||||
} else {
|
} else {
|
||||||
Log.swarningln(FPSTR(L_OT), F("Failed receive fault code"));
|
Log.swarningln(FPSTR(L_OT), F("Failed receive fault code"));
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (vars.slave.fault.code != 0) {
|
} else if (vars.slave.fault.code != 0) {
|
||||||
vars.slave.fault.code = 0;
|
vars.slave.fault.code = 0;
|
||||||
}
|
}
|
||||||
@@ -558,7 +558,7 @@ protected:
|
|||||||
} else {
|
} else {
|
||||||
Log.swarningln(FPSTR(L_OT), F("Failed receive diag code"));
|
Log.swarningln(FPSTR(L_OT), F("Failed receive diag code"));
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (vars.slave.diag.code != 0) {
|
} else if (vars.slave.diag.code != 0) {
|
||||||
vars.slave.diag.code = 0;
|
vars.slave.diag.code = 0;
|
||||||
}
|
}
|
||||||
@@ -767,7 +767,7 @@ protected:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
vars.slave.power.current = power;
|
vars.slave.power.current = power;
|
||||||
|
|
||||||
Log.snoticeln(
|
Log.snoticeln(
|
||||||
FPSTR(L_OT), F("Received modulation level: %hhu%%, power: %.2f of %.2f kW (min: %.2f kW)"),
|
FPSTR(L_OT), F("Received modulation level: %hhu%%, power: %.2f of %.2f kW (min: %.2f kW)"),
|
||||||
vars.slave.modulation.current, vars.slave.power.current,
|
vars.slave.modulation.current, vars.slave.power.current,
|
||||||
@@ -1027,7 +1027,7 @@ protected:
|
|||||||
Log.swarningln(FPSTR(L_OT), F("Failed receive outdoor temp"));
|
Log.swarningln(FPSTR(L_OT), F("Failed receive outdoor temp"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update solar storage temp
|
// Update solar storage temp
|
||||||
if (Sensors::getAmountByType(Sensors::Type::OT_SOLAR_STORAGE_TEMP, true)) {
|
if (Sensors::getAmountByType(Sensors::Type::OT_SOLAR_STORAGE_TEMP, true)) {
|
||||||
if (this->updateSolarStorageTemp()) {
|
if (this->updateSolarStorageTemp()) {
|
||||||
@@ -1195,7 +1195,7 @@ protected:
|
|||||||
if (vars.slave.diag.active) {
|
if (vars.slave.diag.active) {
|
||||||
if (this->instance->sendServiceReset()) {
|
if (this->instance->sendServiceReset()) {
|
||||||
Log.sinfoln(FPSTR(L_OT), F("Boiler diagnostic reset successfully"));
|
Log.sinfoln(FPSTR(L_OT), F("Boiler diagnostic reset successfully"));
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
Log.serrorln(FPSTR(L_OT), F("Boiler diagnostic reset failed"));
|
Log.serrorln(FPSTR(L_OT), F("Boiler diagnostic reset failed"));
|
||||||
}
|
}
|
||||||
@@ -1247,7 +1247,7 @@ protected:
|
|||||||
FPSTR(L_OT_HEATING), F("Set current indoor temp: %.2f (converted: %.2f, response: %.2f)"),
|
FPSTR(L_OT_HEATING), F("Set current indoor temp: %.2f (converted: %.2f, response: %.2f)"),
|
||||||
indoorTemp, convertedTemp, vars.slave.heating.indoorTemp
|
indoorTemp, convertedTemp, vars.slave.heating.indoorTemp
|
||||||
);
|
);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
Log.swarningln(FPSTR(L_OT_HEATING), F("Failed set current indoor temp"));
|
Log.swarningln(FPSTR(L_OT_HEATING), F("Failed set current indoor temp"));
|
||||||
}
|
}
|
||||||
@@ -1401,7 +1401,7 @@ protected:
|
|||||||
);
|
);
|
||||||
|
|
||||||
if (vars.master.heating.overheat) {
|
if (vars.master.heating.overheat) {
|
||||||
if (static_cast<float>(settings.heating.overheatProtection.lowTemp) - highTemp + 0.0001f >= 0.0f) {
|
if ((float) settings.heating.overheatProtection.lowTemp - highTemp + 0.0001f >= 0.0f) {
|
||||||
vars.master.heating.overheat = false;
|
vars.master.heating.overheat = false;
|
||||||
|
|
||||||
Log.sinfoln(
|
Log.sinfoln(
|
||||||
@@ -1411,7 +1411,7 @@ protected:
|
|||||||
}
|
}
|
||||||
|
|
||||||
} else if (vars.slave.heating.active) {
|
} else if (vars.slave.heating.active) {
|
||||||
if (highTemp - static_cast<float>(settings.heating.overheatProtection.highTemp) + 0.0001f >= 0.0f) {
|
if (highTemp - (float) settings.heating.overheatProtection.highTemp + 0.0001f >= 0.0f) {
|
||||||
vars.master.heating.overheat = true;
|
vars.master.heating.overheat = true;
|
||||||
|
|
||||||
Log.swarningln(
|
Log.swarningln(
|
||||||
@@ -1441,7 +1441,7 @@ protected:
|
|||||||
);
|
);
|
||||||
|
|
||||||
if (vars.master.dhw.overheat) {
|
if (vars.master.dhw.overheat) {
|
||||||
if (static_cast<float>(settings.dhw.overheatProtection.lowTemp) - highTemp + 0.0001f >= 0.0f) {
|
if ((float) settings.dhw.overheatProtection.lowTemp - highTemp + 0.0001f >= 0.0f) {
|
||||||
vars.master.dhw.overheat = false;
|
vars.master.dhw.overheat = false;
|
||||||
|
|
||||||
Log.sinfoln(
|
Log.sinfoln(
|
||||||
@@ -1451,7 +1451,7 @@ protected:
|
|||||||
}
|
}
|
||||||
|
|
||||||
} else if (vars.slave.dhw.active) {
|
} else if (vars.slave.dhw.active) {
|
||||||
if (highTemp - static_cast<float>(settings.dhw.overheatProtection.highTemp) + 0.0001f >= 0.0f) {
|
if (highTemp - (float) settings.dhw.overheatProtection.highTemp + 0.0001f >= 0.0f) {
|
||||||
vars.master.dhw.overheat = true;
|
vars.master.dhw.overheat = true;
|
||||||
|
|
||||||
Log.swarningln(
|
Log.swarningln(
|
||||||
@@ -1480,10 +1480,10 @@ protected:
|
|||||||
|
|
||||||
if (this->setMasterVersion(vars.master.appVersion, vars.master.type)) {
|
if (this->setMasterVersion(vars.master.appVersion, vars.master.type)) {
|
||||||
Log.snoticeln(
|
Log.snoticeln(
|
||||||
FPSTR(L_OT), F("Set master version: %u, type: %u"),
|
FPSTR(L_OT), F("Set master version: %u, type: %u"),
|
||||||
vars.master.appVersion, vars.master.type
|
vars.master.appVersion, vars.master.type
|
||||||
);
|
);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
Log.swarningln(FPSTR(L_OT), F("Failed set master version"));
|
Log.swarningln(FPSTR(L_OT), F("Failed set master version"));
|
||||||
}
|
}
|
||||||
@@ -1517,7 +1517,7 @@ protected:
|
|||||||
FPSTR(L_OT), F("Set master member id: %u, flags: %u"),
|
FPSTR(L_OT), F("Set master member id: %u, flags: %u"),
|
||||||
vars.master.memberId, vars.master.flags
|
vars.master.memberId, vars.master.flags
|
||||||
);
|
);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
Log.swarningln(FPSTR(L_OT), F("Failed set master config"));
|
Log.swarningln(FPSTR(L_OT), F("Failed set master config"));
|
||||||
}
|
}
|
||||||
@@ -1561,7 +1561,7 @@ protected:
|
|||||||
OpenThermMessageID::SConfigSMemberIDcode,
|
OpenThermMessageID::SConfigSMemberIDcode,
|
||||||
0
|
0
|
||||||
));
|
));
|
||||||
|
|
||||||
if (!CustomOpenTherm::isValidResponse(response)) {
|
if (!CustomOpenTherm::isValidResponse(response)) {
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@@ -1633,7 +1633,7 @@ protected:
|
|||||||
const unsigned int request = ((dayOfWeek & 0x07) << 13)
|
const unsigned int request = ((dayOfWeek & 0x07) << 13)
|
||||||
| ((ptm->tm_hour & 0x1F) << 8)
|
| ((ptm->tm_hour & 0x1F) << 8)
|
||||||
| (ptm->tm_min & 0x3F);
|
| (ptm->tm_min & 0x3F);
|
||||||
|
|
||||||
const unsigned long response = this->instance->sendRequest(CustomOpenTherm::buildRequest(
|
const unsigned long response = this->instance->sendRequest(CustomOpenTherm::buildRequest(
|
||||||
OpenThermRequestType::WRITE_DATA,
|
OpenThermRequestType::WRITE_DATA,
|
||||||
OpenThermMessageID::DayTime,
|
OpenThermMessageID::DayTime,
|
||||||
@@ -1892,11 +1892,11 @@ protected:
|
|||||||
* From slave member id code:
|
* From slave member id code:
|
||||||
* id: slave.memberIdCode & 0xFF,
|
* id: slave.memberIdCode & 0xFF,
|
||||||
* flags: (slave.memberIdCode & 0xFFFF) >> 8
|
* flags: (slave.memberIdCode & 0xFFFF) >> 8
|
||||||
* @param id
|
* @param id
|
||||||
* @param flags
|
* @param flags
|
||||||
* @param force
|
* @param force
|
||||||
* @return true
|
* @return true
|
||||||
* @return false
|
* @return false
|
||||||
*/
|
*/
|
||||||
bool setMasterConfig(const uint8_t id, const uint8_t flags, const bool force = false) {
|
bool setMasterConfig(const uint8_t id, const uint8_t flags, const bool force = false) {
|
||||||
const uint8_t rMemberId = (force || id > 0) ? id : vars.slave.memberId;
|
const uint8_t rMemberId = (force || id > 0) ? id : vars.slave.memberId;
|
||||||
@@ -2350,7 +2350,7 @@ protected:
|
|||||||
}
|
}
|
||||||
|
|
||||||
vars.slave.dhw.flowRate = value;
|
vars.slave.dhw.flowRate = value;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2393,7 +2393,7 @@ protected:
|
|||||||
}
|
}
|
||||||
|
|
||||||
vars.slave.heating.returnTemp = CustomOpenTherm::getFloat(response);
|
vars.slave.heating.returnTemp = CustomOpenTherm::getFloat(response);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2432,7 +2432,7 @@ protected:
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const float value = CustomOpenTherm::getInt(response);
|
const float value = (float) CustomOpenTherm::getInt(response);
|
||||||
if (!isValidTemp(value, settings.opentherm.unitSystem, -40, 500)) {
|
if (!isValidTemp(value, settings.opentherm.unitSystem, -40, 500)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -2456,7 +2456,7 @@ protected:
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const float value = CustomOpenTherm::getInt(response);
|
const float value = (float) CustomOpenTherm::getInt(response);
|
||||||
if (value <= 0) {
|
if (value <= 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -2500,7 +2500,7 @@ protected:
|
|||||||
}
|
}
|
||||||
|
|
||||||
vars.slave.solar.storage = CustomOpenTherm::getFloat(response);
|
vars.slave.solar.storage = CustomOpenTherm::getFloat(response);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2519,7 +2519,7 @@ protected:
|
|||||||
}
|
}
|
||||||
|
|
||||||
vars.slave.solar.collector = CustomOpenTherm::getFloat(response);
|
vars.slave.solar.collector = CustomOpenTherm::getFloat(response);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+13
-17
@@ -18,7 +18,7 @@ extern WebSerial* webSerial;
|
|||||||
|
|
||||||
class PortalTask : public LeanTask {
|
class PortalTask : public LeanTask {
|
||||||
public:
|
public:
|
||||||
explicit PortalTask(bool _enabled = false, unsigned long _interval = 0) : LeanTask(_enabled, _interval) {
|
PortalTask(bool _enabled = false, unsigned long _interval = 0) : LeanTask(_enabled, _interval) {
|
||||||
this->webServer = new AsyncWebServer(80);
|
this->webServer = new AsyncWebServer(80);
|
||||||
this->dnsServer = new DNSServer();
|
this->dnsServer = new DNSServer();
|
||||||
}
|
}
|
||||||
@@ -73,7 +73,7 @@ protected:
|
|||||||
if (request->authenticate(settings.portal.login, settings.portal.password, PROJECT_NAME)) {
|
if (request->authenticate(settings.portal.login, settings.portal.password, PROJECT_NAME)) {
|
||||||
return next();
|
return next();
|
||||||
}
|
}
|
||||||
|
|
||||||
return request->requestAuthentication(AsyncAuthType::AUTH_BASIC, PROJECT_NAME, "Authentication failed");
|
return request->requestAuthentication(AsyncAuthType::AUTH_BASIC, PROJECT_NAME, "Authentication failed");
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -235,7 +235,7 @@ protected:
|
|||||||
if (sensorId < 0 || sensorId > 255 || !Sensors::isValidSensorId(sensorId)) {
|
if (sensorId < 0 || sensorId > 255 || !Sensors::isValidSensorId(sensorId)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (jsonToSensorSettings(sensorId, sensor.value(), Sensors::settings[sensorId])) {
|
if (jsonToSensorSettings(sensorId, sensor.value(), Sensors::settings[sensorId])) {
|
||||||
fsSensorsSettings.update();
|
fsSensorsSettings.update();
|
||||||
changed = true;
|
changed = true;
|
||||||
@@ -407,7 +407,7 @@ protected:
|
|||||||
responseDoc[sensorId] = Sensors::settings[sensorId].name;
|
responseDoc[sensorId] = Sensors::settings[sensorId].name;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// send response
|
// send response
|
||||||
response->setLength();
|
response->setLength();
|
||||||
request->send(response);
|
request->send(response);
|
||||||
@@ -436,7 +436,7 @@ protected:
|
|||||||
response->setLength();
|
response->setLength();
|
||||||
request->send(response);
|
request->send(response);
|
||||||
}).addMiddleware(&authMiddleware);
|
}).addMiddleware(&authMiddleware);
|
||||||
|
|
||||||
auto& ssHandler = this->webServer->on("/api/sensor", HTTP_POST, [](AsyncWebServerRequest *request, JsonVariant &requestDoc) {
|
auto& ssHandler = this->webServer->on("/api/sensor", HTTP_POST, [](AsyncWebServerRequest *request, JsonVariant &requestDoc) {
|
||||||
if (vars.states.restarting) {
|
if (vars.states.restarting) {
|
||||||
return request->send(503);
|
return request->send(503);
|
||||||
@@ -459,7 +459,7 @@ protected:
|
|||||||
if (!Sensors::isValidSensorId(sensorId)) {
|
if (!Sensors::isValidSensorId(sensorId)) {
|
||||||
return request->send(404);
|
return request->send(404);
|
||||||
}
|
}
|
||||||
|
|
||||||
// prepare request
|
// prepare request
|
||||||
auto prevSettings = Sensors::settings[sensorId];
|
auto prevSettings = Sensors::settings[sensorId];
|
||||||
bool changed = jsonToSensorSettings(sensorId, requestDoc, Sensors::settings[sensorId]);
|
bool changed = jsonToSensorSettings(sensorId, requestDoc, Sensors::settings[sensorId]);
|
||||||
@@ -471,7 +471,7 @@ protected:
|
|||||||
|
|
||||||
auto& sSettings = Sensors::settings[sensorId];
|
auto& sSettings = Sensors::settings[sensorId];
|
||||||
sensorSettingsToJson(sensorId, sSettings, responseDoc);
|
sensorSettingsToJson(sensorId, sSettings, responseDoc);
|
||||||
|
|
||||||
// send response
|
// send response
|
||||||
response->setLength();
|
response->setLength();
|
||||||
response->setCode(changed ? 201 : 200);
|
response->setCode(changed ? 201 : 200);
|
||||||
@@ -515,7 +515,7 @@ protected:
|
|||||||
auto *response = new AsyncJsonResponse();
|
auto *response = new AsyncJsonResponse();
|
||||||
auto& responseDoc = response->getRoot();
|
auto& responseDoc = response->getRoot();
|
||||||
varsToJson(vars, responseDoc);
|
varsToJson(vars, responseDoc);
|
||||||
|
|
||||||
// send response
|
// send response
|
||||||
response->setLength();
|
response->setLength();
|
||||||
response->setCode(changed ? 201 : 200);
|
response->setCode(changed ? 201 : 200);
|
||||||
@@ -570,7 +570,7 @@ protected:
|
|||||||
docPsram[FPSTR(S_FREE)] = ESP.getFreePsram();
|
docPsram[FPSTR(S_FREE)] = ESP.getFreePsram();
|
||||||
docPsram[FPSTR(S_MIN_FREE)] = ESP.getMinFreePsram();
|
docPsram[FPSTR(S_MIN_FREE)] = ESP.getMinFreePsram();
|
||||||
docPsram[FPSTR(S_MAX_FREE_BLOCK)] = ESP.getMaxAllocPsram();
|
docPsram[FPSTR(S_MAX_FREE_BLOCK)] = ESP.getMaxAllocPsram();
|
||||||
|
|
||||||
auto docChip = doc[FPSTR(S_CHIP)].to<JsonObject>();
|
auto docChip = doc[FPSTR(S_CHIP)].to<JsonObject>();
|
||||||
docChip[FPSTR(S_MODEL)] = ESP.getChipModel();
|
docChip[FPSTR(S_MODEL)] = ESP.getChipModel();
|
||||||
docChip[FPSTR(S_REV)] = ESP.getChipRevision();
|
docChip[FPSTR(S_REV)] = ESP.getChipRevision();
|
||||||
@@ -605,7 +605,7 @@ protected:
|
|||||||
docHeap[FPSTR(S_MIN_FREE)] = getFreeHeap(true);
|
docHeap[FPSTR(S_MIN_FREE)] = getFreeHeap(true);
|
||||||
docHeap[FPSTR(S_MAX_FREE_BLOCK)] = getMaxFreeBlockHeap();
|
docHeap[FPSTR(S_MAX_FREE_BLOCK)] = getMaxFreeBlockHeap();
|
||||||
docHeap[FPSTR(S_MIN_MAX_FREE_BLOCK)] = getMaxFreeBlockHeap(true);
|
docHeap[FPSTR(S_MIN_MAX_FREE_BLOCK)] = getMaxFreeBlockHeap(true);
|
||||||
|
|
||||||
auto docChip = doc[FPSTR(S_CHIP)].to<JsonObject>();
|
auto docChip = doc[FPSTR(S_CHIP)].to<JsonObject>();
|
||||||
docChip[FPSTR(S_MODEL)] = ESP.getChipModel();
|
docChip[FPSTR(S_MODEL)] = ESP.getChipModel();
|
||||||
docChip[FPSTR(S_REV)] = ESP.getChipRevision();
|
docChip[FPSTR(S_REV)] = ESP.getChipRevision();
|
||||||
@@ -810,13 +810,9 @@ protected:
|
|||||||
|
|
||||||
static void getFilename(char* filename, size_t maxSizeFilename, const char* type) {
|
static void getFilename(char* filename, size_t maxSizeFilename, const char* type) {
|
||||||
const time_t now = time(nullptr);
|
const time_t now = time(nullptr);
|
||||||
|
const tm* localNow = localtime(&now);
|
||||||
tm localNow {};
|
|
||||||
localtime_r(&now, &localNow);
|
|
||||||
|
|
||||||
char localNowValue[20];
|
char localNowValue[20];
|
||||||
strftime(localNowValue, sizeof(localNowValue), PSTR("%Y-%m-%d-%H-%M-%S"), &localNow);
|
strftime(localNowValue, sizeof(localNowValue), PSTR("%Y-%m-%d-%H-%M-%S"), localNow);
|
||||||
|
|
||||||
snprintf_P(filename, maxSizeFilename, PSTR("%s_%s_%s.json"), networkSettings.hostname, localNowValue, type);
|
snprintf_P(filename, maxSizeFilename, PSTR("%s_%s_%s.json"), networkSettings.hostname, localNowValue, type);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
+3
-3
@@ -5,7 +5,7 @@ GyverPID pidRegulator(0, 0, 0);
|
|||||||
|
|
||||||
class RegulatorTask : public LeanTask {
|
class RegulatorTask : public LeanTask {
|
||||||
public:
|
public:
|
||||||
explicit RegulatorTask(bool _enabled = false, unsigned long _interval = 0) : LeanTask(_enabled, _interval) {}
|
RegulatorTask(bool _enabled = false, unsigned long _interval = 0) : LeanTask(_enabled, _interval) {}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
float prevHeatingTarget = 0.0f;
|
float prevHeatingTarget = 0.0f;
|
||||||
@@ -23,7 +23,7 @@ protected:
|
|||||||
uint32_t getTaskStackSize() override {
|
uint32_t getTaskStackSize() override {
|
||||||
return 5000;
|
return 5000;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*BaseType_t getTaskCore() override {
|
/*BaseType_t getTaskCore() override {
|
||||||
return 1;
|
return 1;
|
||||||
}*/
|
}*/
|
||||||
@@ -158,7 +158,7 @@ protected:
|
|||||||
1.0f / settings.equitherm.exponent
|
1.0f / settings.equitherm.exponent
|
||||||
);
|
);
|
||||||
float etResult = settings.heating.target + settings.equitherm.shift + sf * (
|
float etResult = settings.heating.target + settings.equitherm.shift + sf * (
|
||||||
tempDelta >= 0
|
tempDelta >= 0
|
||||||
? pow(tempDelta, 1.0f / settings.equitherm.exponent)
|
? pow(tempDelta, 1.0f / settings.equitherm.exponent)
|
||||||
: -(pow(-(tempDelta), 1.0f / settings.equitherm.exponent))
|
: -(pow(-(tempDelta), 1.0f / settings.equitherm.exponent))
|
||||||
);
|
);
|
||||||
|
|||||||
+17
-17
@@ -35,7 +35,7 @@ public:
|
|||||||
OT_HEATING_PUMP_HOURS = 25,
|
OT_HEATING_PUMP_HOURS = 25,
|
||||||
OT_DHW_PUMP_HOURS = 26,
|
OT_DHW_PUMP_HOURS = 26,
|
||||||
OT_COOLING_HOURS = 27,
|
OT_COOLING_HOURS = 27,
|
||||||
|
|
||||||
NTC_10K_TEMP = 50,
|
NTC_10K_TEMP = 50,
|
||||||
DALLAS_TEMP = 51,
|
DALLAS_TEMP = 51,
|
||||||
BLUETOOTH = 52,
|
BLUETOOTH = 52,
|
||||||
@@ -198,7 +198,7 @@ public:
|
|||||||
|
|
||||||
auto& sSensor = settings[sensorId];
|
auto& sSensor = settings[sensorId];
|
||||||
auto& rSensor = results[sensorId];
|
auto& rSensor = results[sensorId];
|
||||||
|
|
||||||
float compensatedValue = value;
|
float compensatedValue = value;
|
||||||
if (sSensor.type == Type::HEATING_SETPOINT_TEMP || sSensor.type == Type::MANUAL) {
|
if (sSensor.type == Type::HEATING_SETPOINT_TEMP || sSensor.type == Type::MANUAL) {
|
||||||
rSensor.values[valueId] = compensatedValue;
|
rSensor.values[valueId] = compensatedValue;
|
||||||
@@ -221,7 +221,7 @@ public:
|
|||||||
|
|
||||||
if (sSensor.filtering && fabsf(rSensor.values[valueId]) >= 0.1f) {
|
if (sSensor.filtering && fabsf(rSensor.values[valueId]) >= 0.1f) {
|
||||||
rSensor.values[valueId] += (compensatedValue - rSensor.values[valueId]) * sSensor.filteringFactor;
|
rSensor.values[valueId] += (compensatedValue - rSensor.values[valueId]) * sSensor.filteringFactor;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
rSensor.values[valueId] = compensatedValue;
|
rSensor.values[valueId] = compensatedValue;
|
||||||
}
|
}
|
||||||
@@ -254,11 +254,11 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
uint8_t updated = 0;
|
uint8_t updated = 0;
|
||||||
|
|
||||||
// read sensors data for current instance
|
// read sensors data for current instance
|
||||||
for (uint8_t sensorId = 0; sensorId <= getMaxSensorId(); sensorId++) {
|
for (uint8_t sensorId = 0; sensorId <= getMaxSensorId(); sensorId++) {
|
||||||
auto& sSensor = settings[sensorId];
|
auto& sSensor = settings[sensorId];
|
||||||
|
|
||||||
// only target & valid sensors
|
// only target & valid sensors
|
||||||
if (!sSensor.enabled || sSensor.type != type) {
|
if (!sSensor.enabled || sSensor.type != type) {
|
||||||
continue;
|
continue;
|
||||||
@@ -301,7 +301,7 @@ public:
|
|||||||
FPSTR(L_SENSORS), F("#%hhu '%s' new status: %s"),
|
FPSTR(L_SENSORS), F("#%hhu '%s' new status: %s"),
|
||||||
sensorId, sSensor.name, status ? F("CONNECTED") : F("DISCONNECTED")
|
sensorId, sSensor.name, status ? F("CONNECTED") : F("DISCONNECTED")
|
||||||
);
|
);
|
||||||
|
|
||||||
rSensor.connected = status;
|
rSensor.connected = status;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -318,11 +318,11 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
uint8_t updated = 0;
|
uint8_t updated = 0;
|
||||||
|
|
||||||
// read sensors data for current instance
|
// read sensors data for current instance
|
||||||
for (uint8_t sensorId = 0; sensorId <= getMaxSensorId(); sensorId++) {
|
for (uint8_t sensorId = 0; sensorId <= getMaxSensorId(); sensorId++) {
|
||||||
auto& sSensor = settings[sensorId];
|
auto& sSensor = settings[sensorId];
|
||||||
|
|
||||||
// only target & valid sensors
|
// only target & valid sensors
|
||||||
if (!sSensor.enabled || sSensor.type != type) {
|
if (!sSensor.enabled || sSensor.type != type) {
|
||||||
continue;
|
continue;
|
||||||
@@ -345,7 +345,7 @@ public:
|
|||||||
if (!isValidValueId(valueId)) {
|
if (!isValidValueId(valueId)) {
|
||||||
return defaultValue;
|
return defaultValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
float value = 0.0f;
|
float value = 0.0f;
|
||||||
uint8_t amount = 0;
|
uint8_t amount = 0;
|
||||||
|
|
||||||
@@ -440,13 +440,13 @@ public:
|
|||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
static String cleanName(T value, char space = ' ') {
|
static String cleanName(T value, char space = ' ') {
|
||||||
String res = value;
|
String res = value;
|
||||||
return cleanName(res, space);
|
return cleanName(res, space);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
static String& makeObjectId(String& res, T value, char separator = '_') {
|
static String& makeObjectId(String& res, T value, char separator = '_') {
|
||||||
res = value;
|
res = value;
|
||||||
cleanName(res);
|
cleanName(res);
|
||||||
@@ -456,7 +456,7 @@ public:
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
static String makeObjectId(T value, char separator = '_') {
|
static String makeObjectId(T value, char separator = '_') {
|
||||||
String res;
|
String res;
|
||||||
makeObjectId(res, value, separator);
|
makeObjectId(res, value, separator);
|
||||||
@@ -464,7 +464,7 @@ public:
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class TV, class TS>
|
template <class TV, class TS>
|
||||||
static String& makeObjectIdWithSuffix(String& res, TV value, TS suffix, char separator = '_') {
|
static String& makeObjectIdWithSuffix(String& res, TV value, TS suffix, char separator = '_') {
|
||||||
res.clear();
|
res.clear();
|
||||||
makeObjectId(res, value, separator);
|
makeObjectId(res, value, separator);
|
||||||
@@ -474,14 +474,14 @@ public:
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class TV, class TS>
|
template <class TV, class TS>
|
||||||
static String makeObjectIdWithSuffix(TV value, TS suffix, char separator = '_') {
|
static String makeObjectIdWithSuffix(TV value, TS suffix, char separator = '_') {
|
||||||
String res;
|
String res;
|
||||||
makeObjectIdWithSuffix(res, value, suffix, separator);
|
makeObjectIdWithSuffix(res, value, suffix, separator);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class TV, class TP>
|
template <class TV, class TP>
|
||||||
static String& makeObjectIdWithPrefix(String& res, TV value, TP prefix, char separator = '_') {
|
static String& makeObjectIdWithPrefix(String& res, TV value, TP prefix, char separator = '_') {
|
||||||
res = prefix;
|
res = prefix;
|
||||||
res += separator;
|
res += separator;
|
||||||
@@ -490,7 +490,7 @@ public:
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class TV, class TP>
|
template <class TV, class TP>
|
||||||
static String makeObjectIdWithPrefix(TV value, TP prefix, char separator = '_') {
|
static String makeObjectIdWithPrefix(TV value, TP prefix, char separator = '_') {
|
||||||
String res;
|
String res;
|
||||||
return makeObjectIdWithPrefix(res, value, prefix, separator);
|
return makeObjectIdWithPrefix(res, value, prefix, separator);
|
||||||
@@ -503,4 +503,4 @@ public:
|
|||||||
|
|
||||||
uint8_t Sensors::maxSensors = 0;
|
uint8_t Sensors::maxSensors = 0;
|
||||||
Sensors::Settings* Sensors::settings = nullptr;
|
Sensors::Settings* Sensors::settings = nullptr;
|
||||||
Sensors::Result* Sensors::results = nullptr;
|
Sensors::Result* Sensors::results = nullptr;
|
||||||
+19
-19
@@ -74,7 +74,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
static bool parseAtcData(const NimBLEAdvertisedDevice* device, uint8_t sensorId) {
|
static bool parseAtcData(const NimBLEAdvertisedDevice* device, uint8_t sensorId) {
|
||||||
NimBLEUUID serviceUuid(static_cast<uint16_t>(0x181A));
|
NimBLEUUID serviceUuid((uint16_t) 0x181A);
|
||||||
|
|
||||||
auto serviceData = device->getServiceData(serviceUuid);
|
auto serviceData = device->getServiceData(serviceUuid);
|
||||||
if (!serviceData.size()) {
|
if (!serviceData.size()) {
|
||||||
@@ -91,7 +91,7 @@ public:
|
|||||||
);
|
);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Log.snoticeln(
|
Log.snoticeln(
|
||||||
FPSTR(L_SENSORS_BLE), F("Sensor #%hhu, service %s: found ATC1441 format"),
|
FPSTR(L_SENSORS_BLE), F("Sensor #%hhu, service %s: found ATC1441 format"),
|
||||||
sensorId, serviceUuid.toString().c_str()
|
sensorId, serviceUuid.toString().c_str()
|
||||||
@@ -125,7 +125,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
static bool parsePvvxData(const NimBLEAdvertisedDevice* device, uint8_t sensorId) {
|
static bool parsePvvxData(const NimBLEAdvertisedDevice* device, uint8_t sensorId) {
|
||||||
NimBLEUUID serviceUuid(static_cast<uint16_t>(0x181A));
|
NimBLEUUID serviceUuid((uint16_t) 0x181A);
|
||||||
|
|
||||||
auto serviceData = device->getServiceData(serviceUuid);
|
auto serviceData = device->getServiceData(serviceUuid);
|
||||||
if (!serviceData.size()) {
|
if (!serviceData.size()) {
|
||||||
@@ -142,7 +142,7 @@ public:
|
|||||||
);
|
);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Log.snoticeln(
|
Log.snoticeln(
|
||||||
FPSTR(L_SENSORS_BLE), F("Sensor #%hhu, service %s: found PVVX format"),
|
FPSTR(L_SENSORS_BLE), F("Sensor #%hhu, service %s: found PVVX format"),
|
||||||
sensorId, serviceUuid.toString().c_str()
|
sensorId, serviceUuid.toString().c_str()
|
||||||
@@ -178,7 +178,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
static bool parseBTHomeData(const NimBLEAdvertisedDevice* device, uint8_t sensorId) {
|
static bool parseBTHomeData(const NimBLEAdvertisedDevice* device, uint8_t sensorId) {
|
||||||
NimBLEUUID serviceUuid(static_cast<uint16_t>(0xFCD2));
|
NimBLEUUID serviceUuid((uint16_t) 0xFCD2);
|
||||||
|
|
||||||
auto serviceData = device->getServiceData(serviceUuid);
|
auto serviceData = device->getServiceData(serviceUuid);
|
||||||
if (!serviceData.size()) {
|
if (!serviceData.size()) {
|
||||||
@@ -202,7 +202,7 @@ public:
|
|||||||
);
|
);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Log.snoticeln(
|
Log.snoticeln(
|
||||||
FPSTR(L_SENSORS_BLE), F("Sensor #%hhu, service %s: found BTHome format"),
|
FPSTR(L_SENSORS_BLE), F("Sensor #%hhu, service %s: found BTHome format"),
|
||||||
sensorId, serviceUuid.toString().c_str()
|
sensorId, serviceUuid.toString().c_str()
|
||||||
@@ -263,7 +263,7 @@ public:
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t rawHumidity = (static_cast<uint16_t>(serviceData[serviceDataPos + 1]) << 8)
|
uint16_t rawHumidity = (static_cast<uint16_t>(serviceData[serviceDataPos + 1]) << 8)
|
||||||
| static_cast<uint8_t>(serviceData[serviceDataPos]);
|
| static_cast<uint8_t>(serviceData[serviceDataPos]);
|
||||||
float humidity = static_cast<float>(rawHumidity) * 0.01f;
|
float humidity = static_cast<float>(rawHumidity) * 0.01f;
|
||||||
Sensors::setValueById(sensorId, humidity, Sensors::ValueType::HUMIDITY, true, true);
|
Sensors::setValueById(sensorId, humidity, Sensors::ValueType::HUMIDITY, true, true);
|
||||||
@@ -283,7 +283,7 @@ public:
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t batteryMv = (static_cast<uint16_t>(serviceData[serviceDataPos + 1]) << 8)
|
uint16_t batteryMv = (static_cast<uint16_t>(serviceData[serviceDataPos + 1]) << 8)
|
||||||
| static_cast<uint8_t>(serviceData[serviceDataPos]);
|
| static_cast<uint8_t>(serviceData[serviceDataPos]);
|
||||||
serviceDataPos += 2;
|
serviceDataPos += 2;
|
||||||
foundData = true;
|
foundData = true;
|
||||||
@@ -304,7 +304,7 @@ public:
|
|||||||
|
|
||||||
class SensorsTask : public LeanTask {
|
class SensorsTask : public LeanTask {
|
||||||
public:
|
public:
|
||||||
explicit SensorsTask(bool _enabled = false, unsigned long _interval = 0) : LeanTask(_enabled, _interval) {
|
SensorsTask(bool _enabled = false, unsigned long _interval = 0) : LeanTask(_enabled, _interval) {
|
||||||
this->gpioLastPollingTime.reserve(2);
|
this->gpioLastPollingTime.reserve(2);
|
||||||
|
|
||||||
// OneWire
|
// OneWire
|
||||||
@@ -506,7 +506,7 @@ protected:
|
|||||||
|
|
||||||
for (uint8_t sensorId = 0; sensorId <= Sensors::getMaxSensorId(); sensorId++) {
|
for (uint8_t sensorId = 0; sensorId <= Sensors::getMaxSensorId(); sensorId++) {
|
||||||
auto& sSensor = Sensors::settings[sensorId];
|
auto& sSensor = Sensors::settings[sensorId];
|
||||||
|
|
||||||
if (!sSensor.enabled || sSensor.type != Sensors::Type::DALLAS_TEMP || sSensor.purpose == Sensors::Purpose::NOT_CONFIGURED) {
|
if (!sSensor.enabled || sSensor.type != Sensors::Type::DALLAS_TEMP || sSensor.purpose == Sensors::Purpose::NOT_CONFIGURED) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -560,7 +560,7 @@ protected:
|
|||||||
// check & filling sensors address
|
// check & filling sensors address
|
||||||
for (uint8_t sensorId = 0; sensorId <= Sensors::getMaxSensorId(); sensorId++) {
|
for (uint8_t sensorId = 0; sensorId <= Sensors::getMaxSensorId(); sensorId++) {
|
||||||
auto& sSensor = Sensors::settings[sensorId];
|
auto& sSensor = Sensors::settings[sensorId];
|
||||||
|
|
||||||
if (!sSensor.enabled || sSensor.type != Sensors::Type::DALLAS_TEMP || sSensor.purpose == Sensors::Purpose::NOT_CONFIGURED) {
|
if (!sSensor.enabled || sSensor.type != Sensors::Type::DALLAS_TEMP || sSensor.purpose == Sensors::Purpose::NOT_CONFIGURED) {
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@@ -593,7 +593,7 @@ protected:
|
|||||||
if (sCheckingSensor.type != Sensors::Type::DALLAS_TEMP || checkingSensorId == sensorId) {
|
if (sCheckingSensor.type != Sensors::Type::DALLAS_TEMP || checkingSensorId == sensorId) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sCheckingSensor.gpio != sSensor.gpio || isEmptyAddress(sCheckingSensor.address)) {
|
if (sCheckingSensor.gpio != sSensor.gpio || isEmptyAddress(sCheckingSensor.address)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -654,7 +654,7 @@ protected:
|
|||||||
// read sensors data for current instance
|
// read sensors data for current instance
|
||||||
for (uint8_t sensorId = 0; sensorId <= Sensors::getMaxSensorId(); sensorId++) {
|
for (uint8_t sensorId = 0; sensorId <= Sensors::getMaxSensorId(); sensorId++) {
|
||||||
auto& sSensor = Sensors::settings[sensorId];
|
auto& sSensor = Sensors::settings[sensorId];
|
||||||
|
|
||||||
// only target & valid sensors
|
// only target & valid sensors
|
||||||
if (!sSensor.enabled || sSensor.type != Sensors::Type::DALLAS_TEMP || sSensor.purpose == Sensors::Purpose::NOT_CONFIGURED) {
|
if (!sSensor.enabled || sSensor.type != Sensors::Type::DALLAS_TEMP || sSensor.purpose == Sensors::Purpose::NOT_CONFIGURED) {
|
||||||
continue;
|
continue;
|
||||||
@@ -662,7 +662,7 @@ protected:
|
|||||||
} else if (sSensor.gpio != gpio || isEmptyAddress(sSensor.address)) {
|
} else if (sSensor.gpio != gpio || isEmptyAddress(sSensor.address)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto& rSensor = Sensors::results[sensorId];
|
auto& rSensor = Sensors::results[sensorId];
|
||||||
float value = instance.getTempC(sSensor.address);
|
float value = instance.getTempC(sSensor.address);
|
||||||
if (value == DEVICE_DISCONNECTED_C) {
|
if (value == DEVICE_DISCONNECTED_C) {
|
||||||
@@ -721,7 +721,7 @@ protected:
|
|||||||
|
|
||||||
for (uint8_t sensorId = 0; sensorId <= Sensors::getMaxSensorId(); sensorId++) {
|
for (uint8_t sensorId = 0; sensorId <= Sensors::getMaxSensorId(); sensorId++) {
|
||||||
auto& sSensor = Sensors::settings[sensorId];
|
auto& sSensor = Sensors::settings[sensorId];
|
||||||
|
|
||||||
if (!sSensor.enabled || sSensor.purpose == Sensors::Purpose::NOT_CONFIGURED) {
|
if (!sSensor.enabled || sSensor.purpose == Sensors::Purpose::NOT_CONFIGURED) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -772,7 +772,7 @@ protected:
|
|||||||
if (rSensor.signalQuality > 0) {
|
if (rSensor.signalQuality > 0) {
|
||||||
rSensor.signalQuality--;
|
rSensor.signalQuality--;
|
||||||
}
|
}
|
||||||
|
|
||||||
this->gpioLastPollingTime[sSensor.gpio] = millis();
|
this->gpioLastPollingTime[sSensor.gpio] = millis();
|
||||||
this->dhtIsPolling = false;
|
this->dhtIsPolling = false;
|
||||||
});
|
});
|
||||||
@@ -805,7 +805,7 @@ protected:
|
|||||||
void pollingNtcSensors() {
|
void pollingNtcSensors() {
|
||||||
for (uint8_t sensorId = 0; sensorId <= Sensors::getMaxSensorId(); sensorId++) {
|
for (uint8_t sensorId = 0; sensorId <= Sensors::getMaxSensorId(); sensorId++) {
|
||||||
auto& sSensor = Sensors::settings[sensorId];
|
auto& sSensor = Sensors::settings[sensorId];
|
||||||
|
|
||||||
if (!sSensor.enabled || sSensor.type != Sensors::Type::NTC_10K_TEMP || sSensor.purpose == Sensors::Purpose::NOT_CONFIGURED) {
|
if (!sSensor.enabled || sSensor.type != Sensors::Type::NTC_10K_TEMP || sSensor.purpose == Sensors::Purpose::NOT_CONFIGURED) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -830,7 +830,7 @@ protected:
|
|||||||
}
|
}
|
||||||
|
|
||||||
const float sensorResistance = value > 1
|
const float sensorResistance = value > 1
|
||||||
? DEFAULT_NTC_REF_RESISTANCE / (DEFAULT_NTC_VREF / static_cast<float>(value) - 1.0f)
|
? DEFAULT_NTC_REF_RESISTANCE / (DEFAULT_NTC_VREF / (float) value - 1.0f)
|
||||||
: 0.0f;
|
: 0.0f;
|
||||||
const float rawTemp = 1.0f / (
|
const float rawTemp = 1.0f / (
|
||||||
1.0f / (DEFAULT_NTC_NOMINAL_TEMP + 273.15f) +
|
1.0f / (DEFAULT_NTC_NOMINAL_TEMP + 273.15f) +
|
||||||
@@ -969,4 +969,4 @@ protected:
|
|||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
+2
-2
@@ -133,7 +133,7 @@ struct Settings {
|
|||||||
uint8_t minTemp = DEFAULT_DHW_MIN_TEMP;
|
uint8_t minTemp = DEFAULT_DHW_MIN_TEMP;
|
||||||
uint8_t maxTemp = DEFAULT_DHW_MAX_TEMP;
|
uint8_t maxTemp = DEFAULT_DHW_MAX_TEMP;
|
||||||
uint8_t maxModulation = 100;
|
uint8_t maxModulation = 100;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
uint8_t highTemp = 95;
|
uint8_t highTemp = 95;
|
||||||
uint8_t lowTemp = 90;
|
uint8_t lowTemp = 90;
|
||||||
@@ -441,4 +441,4 @@ struct Variables {
|
|||||||
bool restarting = false;
|
bool restarting = false;
|
||||||
bool upgrading = false;
|
bool upgrading = false;
|
||||||
} states;
|
} states;
|
||||||
} vars;
|
} vars;
|
||||||
+2
-2
@@ -147,7 +147,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef PROGMEM
|
#ifndef PROGMEM
|
||||||
#define PROGMEM // NOLINT
|
#define PROGMEM
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef ARDUINO_ARCH_ESP32
|
#ifdef ARDUINO_ARCH_ESP32
|
||||||
@@ -168,4 +168,4 @@ enum class HysteresisAction : uint8_t {
|
|||||||
SET_ZERO_TARGET = 1
|
SET_ZERO_TARGET = 1
|
||||||
};
|
};
|
||||||
|
|
||||||
char buffer[255];
|
char buffer[255];
|
||||||
+1
-1
@@ -71,7 +71,7 @@ void setup() {
|
|||||||
|
|
||||||
return tm{sec, min, hour};
|
return tm{sec, min, hour};
|
||||||
});
|
});
|
||||||
|
|
||||||
Serial.begin(115200);
|
Serial.begin(115200);
|
||||||
#if ARDUINO_USB_MODE
|
#if ARDUINO_USB_MODE
|
||||||
Serial.setTxBufferSize(512);
|
Serial.setTxBufferSize(512);
|
||||||
|
|||||||
+2
-2
@@ -1,6 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#ifndef PROGMEM
|
#ifndef PROGMEM
|
||||||
#define PROGMEM // NOLINT
|
#define PROGMEM
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
const char L_SETTINGS[] PROGMEM = "SETTINGS";
|
const char L_SETTINGS[] PROGMEM = "SETTINGS";
|
||||||
@@ -224,4 +224,4 @@ const char S_USE_DHCP[] PROGMEM = "useDhcp";
|
|||||||
const char S_USER[] PROGMEM = "user";
|
const char S_USER[] PROGMEM = "user";
|
||||||
const char S_VALUE[] PROGMEM = "value";
|
const char S_VALUE[] PROGMEM = "value";
|
||||||
const char S_VERSION[] PROGMEM = "version";
|
const char S_VERSION[] PROGMEM = "version";
|
||||||
const char S_WEBSERIAL[] PROGMEM = "webSerial";
|
const char S_WEBSERIAL[] PROGMEM = "webSerial";
|
||||||
+11
-11
@@ -7,7 +7,7 @@ String getChipId(const char* prefix = nullptr, const char* suffix = nullptr) {
|
|||||||
+ (prefix != nullptr ? strlen(prefix) : 0)
|
+ (prefix != nullptr ? strlen(prefix) : 0)
|
||||||
+ (suffix != nullptr ? strlen(suffix) : 0)
|
+ (suffix != nullptr ? strlen(suffix) : 0)
|
||||||
);
|
);
|
||||||
|
|
||||||
if (prefix != nullptr) {
|
if (prefix != nullptr) {
|
||||||
chipId.concat(prefix);
|
chipId.concat(prefix);
|
||||||
}
|
}
|
||||||
@@ -139,7 +139,7 @@ inline bool isValidTemp(const float value, UnitSystem unit, const float min = 0.
|
|||||||
|
|
||||||
float roundf(float value, uint8_t decimals = 2) {
|
float roundf(float value, uint8_t decimals = 2) {
|
||||||
if (decimals == 0) {
|
if (decimals == 0) {
|
||||||
return static_cast<int>(value + 0.5f);
|
return (int)(value + 0.5f);
|
||||||
|
|
||||||
} else if (abs(value) < 0.00000001f) {
|
} else if (abs(value) < 0.00000001f) {
|
||||||
return 0.0f;
|
return 0.0f;
|
||||||
@@ -147,7 +147,7 @@ float roundf(float value, uint8_t decimals = 2) {
|
|||||||
|
|
||||||
float multiplier = pow10(decimals);
|
float multiplier = pow10(decimals);
|
||||||
value += 0.5f / multiplier * (value < 0.0f ? -1.0f : 1.0f);
|
value += 0.5f / multiplier * (value < 0.0f ? -1.0f : 1.0f);
|
||||||
return static_cast<int>(value * multiplier) / multiplier;
|
return (int)(value * multiplier) / multiplier;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline size_t getTotalHeap() {
|
inline size_t getTotalHeap() {
|
||||||
@@ -470,7 +470,7 @@ void settingsToJson(const Settings& src, JsonVariant dst, bool safe = false) {
|
|||||||
otOptions[FPSTR(S_ALWAYS_SEND_INDOOR_TEMP)] = src.opentherm.options.alwaysSendIndoorTemp;
|
otOptions[FPSTR(S_ALWAYS_SEND_INDOOR_TEMP)] = src.opentherm.options.alwaysSendIndoorTemp;
|
||||||
otOptions[FPSTR(S_NATIVE_OTC)] = src.opentherm.options.nativeOTC;
|
otOptions[FPSTR(S_NATIVE_OTC)] = src.opentherm.options.nativeOTC;
|
||||||
otOptions[FPSTR(S_IMMERGAS_FIX)] = src.opentherm.options.immergasFix;
|
otOptions[FPSTR(S_IMMERGAS_FIX)] = src.opentherm.options.immergasFix;
|
||||||
|
|
||||||
|
|
||||||
auto mqtt = dst[FPSTR(S_MQTT)].to<JsonObject>();
|
auto mqtt = dst[FPSTR(S_MQTT)].to<JsonObject>();
|
||||||
mqtt[FPSTR(S_ENABLED)] = src.mqtt.enabled;
|
mqtt[FPSTR(S_ENABLED)] = src.mqtt.enabled;
|
||||||
@@ -486,7 +486,7 @@ void settingsToJson(const Settings& src, JsonVariant dst, bool safe = false) {
|
|||||||
emergency[FPSTR(S_TARGET)] = roundf(src.emergency.target, 2);
|
emergency[FPSTR(S_TARGET)] = roundf(src.emergency.target, 2);
|
||||||
emergency[FPSTR(S_TRESHOLD_TIME)] = src.emergency.tresholdTime;
|
emergency[FPSTR(S_TRESHOLD_TIME)] = src.emergency.tresholdTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto heating = dst[FPSTR(S_HEATING)].to<JsonObject>();
|
auto heating = dst[FPSTR(S_HEATING)].to<JsonObject>();
|
||||||
heating[FPSTR(S_ENABLED)] = src.heating.enabled;
|
heating[FPSTR(S_ENABLED)] = src.heating.enabled;
|
||||||
heating[FPSTR(S_TURBO)] = src.heating.turbo;
|
heating[FPSTR(S_TURBO)] = src.heating.turbo;
|
||||||
@@ -1774,8 +1774,8 @@ bool jsonToSettings(const JsonVariantConst src, Settings& dst, bool safe = false
|
|||||||
float minTemp = indoorTempControl ? THERMOSTAT_INDOOR_MIN_TEMP : dst.heating.minTemp;
|
float minTemp = indoorTempControl ? THERMOSTAT_INDOOR_MIN_TEMP : dst.heating.minTemp;
|
||||||
float maxTemp = indoorTempControl ? THERMOSTAT_INDOOR_MAX_TEMP : dst.heating.maxTemp;
|
float maxTemp = indoorTempControl ? THERMOSTAT_INDOOR_MAX_TEMP : dst.heating.maxTemp;
|
||||||
|
|
||||||
float value = !src[FPSTR(S_HEATING)][FPSTR(S_TARGET)].isNull()
|
float value = !src[FPSTR(S_HEATING)][FPSTR(S_TARGET)].isNull()
|
||||||
? src[FPSTR(S_HEATING)][FPSTR(S_TARGET)].as<float>()
|
? src[FPSTR(S_HEATING)][FPSTR(S_TARGET)].as<float>()
|
||||||
: dst.heating.target;
|
: dst.heating.target;
|
||||||
bool valid = isValidTemp(
|
bool valid = isValidTemp(
|
||||||
value,
|
value,
|
||||||
@@ -1801,8 +1801,8 @@ bool jsonToSettings(const JsonVariantConst src, Settings& dst, bool safe = false
|
|||||||
|
|
||||||
// force check dhw target
|
// force check dhw target
|
||||||
{
|
{
|
||||||
float value = !src[FPSTR(S_DHW)][FPSTR(S_TARGET)].isNull()
|
float value = !src[FPSTR(S_DHW)][FPSTR(S_TARGET)].isNull()
|
||||||
? src[FPSTR(S_DHW)][FPSTR(S_TARGET)].as<float>()
|
? src[FPSTR(S_DHW)][FPSTR(S_TARGET)].as<float>()
|
||||||
: dst.dhw.target;
|
: dst.dhw.target;
|
||||||
bool valid = isValidTemp(
|
bool valid = isValidTemp(
|
||||||
value,
|
value,
|
||||||
@@ -2061,7 +2061,7 @@ bool jsonToSensorSettings(const uint8_t sensorId, const JsonVariantConst src, Se
|
|||||||
for (uint8_t i = 0; i < sizeof(dst.address); i++) {
|
for (uint8_t i = 0; i < sizeof(dst.address); i++) {
|
||||||
dst.address[i] = 0x00;
|
dst.address[i] = 0x00;
|
||||||
}
|
}
|
||||||
|
|
||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2257,4 +2257,4 @@ bool jsonToVars(const JsonVariantConst src, Variables& dst) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return changed;
|
return changed;
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user