Compare commits

..

18 Commits

Author SHA1 Message Date
CaCO3
71766e1c7b prepared changelog for 16.1.0-RC1 2025-12-29 22:43:42 +01:00
PowLee88
d739ad4c91 Enable OV3660 support in sdkconfig.defaults (#3996) 2025-12-29 22:13:31 +01:00
evgbus
71577039f8 Added "Draw from center" option to Analog ROI editor (#3975) 2025-12-29 21:59:04 +01:00
Mallo321123
39de778ffe Add link for top cover and antenna holder (#3988)
* Add link for top cover and antenna holder

* Added Emojis

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-12-29 21:55:07 +01:00
Rick Auch
de4ae71864 Add default_entity_id to MQTT HA autodiscovery payload (#3970)
* HA MQTT autodiscovery topic update

Add `default_entity_id` to the HA autodiscovery payload to address a deprecation (warning starting with HA 2025.11 and causing an error starting with HA 2026.4).

If desired, the `object_id` (line 107) can be removed after April 2026.

* Fix whitespace

* Whitespace again

* Whitespace final
2025-12-29 21:49:41 +01:00
SybexXx
2b09ce6e44 checkDigitConsistency: added ESP_LOG_DEBUG output (#3962)
Refactor doFlow method by removing unused variables and consolidating code.

https://github.com/jomjol/AI-on-the-edge-device/issues/3960#issuecomment-3504126805
2025-12-29 21:47:25 +01:00
Frank Haverland
eb812282d2 dig-class100-0182 model with new lcd images (#3947) 2025-12-29 21:46:38 +01:00
SybexXx
f3e3ce504e setup_fix (#3906)
* Update edit_config_template.html

* Update edit_config_template.html
2025-09-07 17:47:40 +02:00
SybexXx
ba03a7dc38 Migration fix (#3900)
* Update main.cpp

During migration, the messages was issued as errors, although this should be information/should serve for information.

* Update main.cpp

* Update Helper.cpp
2025-09-02 22:06:07 +02:00
Rick Auch
73afc07652 Add option for gal/min rate for Home Assistant MQTT Autodiscovery (#3868)
Add gal/min as an option
2025-08-17 15:27:21 +02:00
Bruns8234
c320e4c921 Update SDCard Manufacturer List (#3730)
Update 1 and added 5 entries
2025-05-05 23:55:10 +02:00
CaCO3
43b29f3408 clarify the parameter prefix (#3717)
Co-authored-by: CaCO3 <caco@ruinelli.ch>
2025-04-23 00:01:37 +02:00
SybexX
b1c65c0a71 Update MeterType.md 2025-04-20 22:03:40 +02:00
CaCO3
00091fc3f9 Update NUMBER.ChangeRateThreshold.md 2025-04-16 23:31:19 +02:00
CaCO3
69a43fb068 Update reply-bot.yaml 2025-04-16 20:43:49 +02:00
CaCO3
82f28cb5bc Fix webinstaller update (#3697)
* Update build.yaml

* Update build.yaml

* Update build.yaml

* Update build.yaml
2025-04-09 23:43:50 +02:00
Frank Haverland
34818c0dc1 new model dig-class100-0180-s2-q (#3684)
* new model dig-class100-0180-s2-q

Model updated to Tensorflow 2.17
new images, now 24300

* Revert "new model dig-class100-0180-s2-q"

This reverts commit 7ac771e4b6.

* new model
2025-04-08 20:22:24 +02:00
jomjol
0b3a6e1057 Update tflite (#3687) 2025-04-06 09:45:48 +02:00
27 changed files with 185 additions and 78 deletions

View File

@@ -1,6 +1,10 @@
name: Build and Pack name: Build and Pack
on: [push, pull_request] on:
push:
pull_request:
release:
types: [released] # Only trigger on published releases (not drafts or pre-released)
jobs: jobs:
######################################################################################### #########################################################################################
@@ -304,7 +308,7 @@ jobs:
prepare-release: prepare-release:
runs-on: ubuntu-latest runs-on: ubuntu-latest
needs: [pack-for-update, pack-for-manual_setup, pack-for-remote_setup] needs: [pack-for-update, pack-for-manual_setup, pack-for-remote_setup]
if: startsWith(github.ref, 'refs/tags/') if: github.event_name == 'release' # Only run when the trigger is a release
# Sets permissions of the GITHUB_TOKEN to allow updating the branches # Sets permissions of the GITHUB_TOKEN to allow updating the branches
permissions: permissions:
@@ -406,7 +410,7 @@ jobs:
######################################################################################### #########################################################################################
# Make sure to also update update-webinstaller.yml! # Make sure to also update update-webinstaller.yml!
update-web-installer: update-web-installer:
if: github.event_name == 'release' && github.event.action == 'published' # Only run on release but not on prerelease if: github.event_name == 'release' # Only run when the trigger is a release
needs: [prepare-release] needs: [prepare-release]
environment: environment:
name: github-pages name: github-pages
@@ -444,13 +448,13 @@ jobs:
sed -i 's/$VERSION/${{ steps.last_release.outputs.tag_name }}/g' webinstaller/manifest.json sed -i 's/$VERSION/${{ steps.last_release.outputs.tag_name }}/g' webinstaller/manifest.json
- name: Setup Pages - name: Setup Pages
uses: actions/configure-pages@v4 uses: actions/configure-pages@v5
- name: Upload artifact - name: Upload artifact
uses: actions/upload-pages-artifact@v2 uses: actions/upload-pages-artifact@v3
with: with:
path: 'webinstaller' path: 'webinstaller'
- name: Deploy to GitHub Pages - name: Deploy to GitHub Pages
id: deployment id: deployment
uses: actions/deploy-pages@v3 # Note: v4 does not work! uses: actions/deploy-pages@v4.0.5 # Note: v4 does not work!

View File

@@ -18,7 +18,7 @@ permissions:
jobs: jobs:
comment: comment:
runs-on: ubuntu-20.04 runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4

View File

@@ -1,4 +1,28 @@
# [16.0.0] - 2024-03-15 # [16.1.0-RC1] - 2025-12-29
For a full list of changes see [Full list of changes](https://github.com/jomjol/AI-on-the-edge-device/compare/v16.0.0...v16.1.0)
### Known issues
No software is perfect. We know that our software has some quirks. If you have an issue, please first check the [issues](https://github.com/jomjol/AI-on-the-edge-device/issues) and
[discussions](https://github.com/jomjol/AI-on-the-edge-device/discussions) before reporting a new issue.
### Core Changes and Bug fixes
- Various minor improvements and changes
- Various documentation corrections/improvements
- Parameter `ChangeRateThreshold` can now also be zero [#3668](https://github.com/jomjol/AI-on-the-edge-device/pull/3668)
- MQTT: Added a proper `device_class` (duration) to "uptime" [#3659](https://github.com/jomjol/AI-on-the-edge-device/pull/3659)
- MQTT: Added `default_entity_id` to MQTT HA autodiscovery payload [#3970](https://github.com/jomjol/AI-on-the-edge-device/pull/3970)
- Added new models
- Updated SDCard Manufacturer List [#3730](https://github.com/jomjol/AI-on-the-edge-device/pull/3730)
- Added option for gal/min rate for Home Assistant MQTT Autodiscovery[#3868](https://github.com/jomjol/AI-on-the-edge-device/pull/3868)
- Fixed Setup Wizard [#3906](https://github.com/jomjol/AI-on-the-edge-device/pull/3906)
- `checkDigitConsistency`: added ESP_LOG_DEBUG output [#3962](https://github.com/jomjol/AI-on-the-edge-device/pull/3962)
- Added "Draw from center" option to Analog ROI editor [#3975](https://github.com/jomjol/AI-on-the-edge-device/pull/3975)
- Enabled OV3660 support in sdkconfig.defaults [#3996](https://github.com/jomjol/AI-on-the-edge-device/pull/3996)
# [16.0.0] - 2025-03-15
For a full list of changes see [Full list of changes](https://github.com/jomjol/AI-on-the-edge-device/compare/v15.7.0...v16.0.0) For a full list of changes see [Full list of changes](https://github.com/jomjol/AI-on-the-edge-device/compare/v15.7.0...v16.0.0)

View File

@@ -166,6 +166,7 @@ Various 3D-printable housings can be found here:
- ⚡ [Power Meter](https://www.thingiverse.com/thing:5028229) - ⚡ [Power Meter](https://www.thingiverse.com/thing:5028229)
- 🔥 [Gas Meter](https://www.thingiverse.com/thing:5224101) - 🔥 [Gas Meter](https://www.thingiverse.com/thing:5224101)
- 📷 [ESP32-cam housing only](https://www.thingiverse.com/thing:4571627) - 📷 [ESP32-cam housing only](https://www.thingiverse.com/thing:4571627)
- 📡 [Top cover and Antenna Holder](https://www.printables.com/model/452139-cover-for-esp32-cam-water-meter)
--- ---

View File

@@ -161,6 +161,9 @@ bool ClassFlowMQTT::ReadParameter(FILE* pfile, string& aktparamgraph)
else if (toUpper(splitted[1]) == "WATER_GAL") { else if (toUpper(splitted[1]) == "WATER_GAL") {
mqttServer_setMeterType("water", "gal", "h", "gal/h"); mqttServer_setMeterType("water", "gal", "h", "gal/h");
} }
else if (toUpper(splitted[1]) == "WATER_GAL_MIN") {
mqttServer_setMeterType("water", "gal", "min", "gal/min"); // min = Minutes
}
else if (toUpper(splitted[1]) == "GAS_M3") { else if (toUpper(splitted[1]) == "GAS_M3") {
mqttServer_setMeterType("gas", "", "h", "m³/h"); mqttServer_setMeterType("gas", "", "h", "m³/h");
} }

View File

@@ -758,17 +758,8 @@ string ClassFlowPostProcessing::ShiftDecimal(string in, int _decShift) {
} }
bool ClassFlowPostProcessing::doFlow(string zwtime) { bool ClassFlowPostProcessing::doFlow(string zwtime) {
string result = "";
string digit = "";
string analog = "";
string zwvalue; string zwvalue;
string zw; time_t imagetime = flowTakeImage->getTimeImageTaken();
time_t imagetime = 0;
string rohwert;
// Update decimal point, as the decimal places can also change when changing from CNNType Auto --> xyz:
imagetime = flowTakeImage->getTimeImageTaken();
if (imagetime == 0) { if (imagetime == 0) {
time(&imagetime); time(&imagetime);
@@ -794,6 +785,7 @@ bool ClassFlowPostProcessing::doFlow(string zwtime) {
// double LastValueTimeDifference = difftime(imagetime, NUMBERS[j]->timeStampLastValue); // in seconds // double LastValueTimeDifference = difftime(imagetime, NUMBERS[j]->timeStampLastValue); // in seconds
double LastPreValueTimeDifference = difftime(imagetime, NUMBERS[j]->timeStampLastPreValue); // in seconds double LastPreValueTimeDifference = difftime(imagetime, NUMBERS[j]->timeStampLastPreValue); // in seconds
// Update decimal point, as the decimal places can also change when changing from CNNType Auto --> xyz:
UpdateNachkommaDecimalShift(); UpdateNachkommaDecimalShift();
int previous_value = -1; int previous_value = -1;
@@ -884,12 +876,15 @@ bool ClassFlowPostProcessing::doFlow(string zwtime) {
if (NUMBERS[j]->checkDigitIncreaseConsistency) { if (NUMBERS[j]->checkDigitIncreaseConsistency) {
if (flowDigit) { if (flowDigit) {
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "Before checkDigitConsistency: value=" + std::to_string(NUMBERS[j]->Value));
NUMBERS[j]->Value = checkDigitConsistency(NUMBERS[j]->Value, NUMBERS[j]->DecimalShift, NUMBERS[j]->analog_roi != NULL, NUMBERS[j]->PreValue); NUMBERS[j]->Value = checkDigitConsistency(NUMBERS[j]->Value, NUMBERS[j]->DecimalShift, NUMBERS[j]->analog_roi != NULL, NUMBERS[j]->PreValue);
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "After checkDigitConsistency: value=" + std::to_string(NUMBERS[j]->Value));
} }
else { else {
#ifdef SERIAL_DEBUG #ifdef SERIAL_DEBUG
ESP_LOGD(TAG, "checkDigitIncreaseConsistency = true - no digit numbers defined!"); ESP_LOGD(TAG, "checkDigitIncreaseConsistency = true - no digit numbers defined!");
#endif #endif
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "checkDigitIncreaseConsistency = true - no digit numbers defined!");
} }
} }
@@ -1128,6 +1123,7 @@ float ClassFlowPostProcessing::checkDigitConsistency(double input, int _decilams
#ifdef SERIAL_DEBUG #ifdef SERIAL_DEBUG
ESP_LOGD(TAG, "checkDigitConsistency: pot=%d, decimalshift=%d", pot, _decilamshift); ESP_LOGD(TAG, "checkDigitConsistency: pot=%d, decimalshift=%d", pot, _decilamshift);
#endif #endif
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "checkDigitConsistency: pot=" + std::to_string(pot) + ", decimalshift=" + std::to_string(_decilamshift));
pot_max = ((int) log10(input)) + 1; pot_max = ((int) log10(input)) + 1;
@@ -1159,6 +1155,7 @@ float ClassFlowPostProcessing::checkDigitConsistency(double input, int _decilams
#ifdef SERIAL_DEBUG #ifdef SERIAL_DEBUG
ESP_LOGD(TAG, "checkDigitConsistency: input=%f", input); ESP_LOGD(TAG, "checkDigitConsistency: input=%f", input);
#endif #endif
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "checkDigitConsistency: input=" + std::to_string(input));
pot++; pot++;
} }

View File

@@ -806,11 +806,21 @@ struct SDCard_Manufacturer_database sd_database[] = {
.id = 0x03, .id = 0x03,
.manufacturer = "SanDisk", .manufacturer = "SanDisk",
}, },
{
.type = "sd",
.id = 0x05,
.manufacturer = "Lenovo",
},
{ {
.type = "sd", .type = "sd",
.id = 0x08, .id = 0x08,
.manufacturer = "Silicon Power", .manufacturer = "Silicon Power",
}, },
{
.type = "sd",
.id = 0x09,
.manufacturer = "ATP",
},
{ {
.type = "sd", .type = "sd",
.id = 0x18, .id = 0x18,
@@ -894,7 +904,27 @@ struct SDCard_Manufacturer_database sd_database[] = {
{ {
.type = "sd", .type = "sd",
.id = 0x89, .id = 0x89,
.manufacturer = "Unknown", .manufacturer = "Netac",
},
{
.type = "sd",
.id = 0x9f,
.manufacturer = "Kingston/Kodak/Silicon Power",
},
{
.type = "sd",
.id = 0xad,
.manufacturer = "Amazon Basics/Lexar/OV",
},
{
.type = "sd",
.id = 0xdf,
.manufacturer = "Lenovo",
},
{
.type = "sd",
.id = 0xfe,
.manufacturer = "Bekit/Cloudisk/HP/Reletech",
}, },
}; };
@@ -1218,7 +1248,7 @@ bool replaceString(std::string &s, std::string const &toReplace, std::string con
if (logIt) if (logIt)
{ {
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Migrated Configfile line '" + old + "' to '" + s + "'"); LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Migrated Configfile line '" + old + "' to '" + s + "'");
} }
return true; return true;

View File

@@ -72,6 +72,7 @@ bool sendHomeAssistantDiscoveryTopic(std::string group, std::string field,
std::string topicFull; std::string topicFull;
std::string configTopic; std::string configTopic;
std::string payload; std::string payload;
std::string component;
configTopic = field; configTopic = field;
@@ -80,6 +81,16 @@ bool sendHomeAssistantDiscoveryTopic(std::string group, std::string field,
name = group + " " + name; name = group + " " + name;
} }
if (field == "problem") { // Special case: Binary sensor which is based on error topic
component = "binary_sensor";
}
else if (field == "flowstart") { // Special case: Button
component = "button";
}
else {
component = "sensor";
}
/** /**
* homeassistant needs the MQTT discovery topic according to the following structure: * homeassistant needs the MQTT discovery topic according to the following structure:
* <discovery_prefix>/<component>/[<node_id>/]<object_id>/config * <discovery_prefix>/<component>/[<node_id>/]<object_id>/config
@@ -87,21 +98,14 @@ bool sendHomeAssistantDiscoveryTopic(std::string group, std::string field,
* This means a maintopic "home/test/watermeter" is transformed to the discovery topic "homeassistant/sensor/watermeter/..." * This means a maintopic "home/test/watermeter" is transformed to the discovery topic "homeassistant/sensor/watermeter/..."
*/ */
std::string node_id = createNodeId(maintopic); std::string node_id = createNodeId(maintopic);
if (field == "problem") { // Special case: Binary sensor which is based on error topic topicFull = "homeassistant/" + component + "/" + node_id + "/" + configTopic + "/config";
topicFull = "homeassistant/binary_sensor/" + node_id + "/" + configTopic + "/config";
}
else if (field == "flowstart") { // Special case: Button
topicFull = "homeassistant/button/" + node_id + "/" + configTopic + "/config";
}
else {
topicFull = "homeassistant/sensor/" + node_id + "/" + configTopic + "/config";
}
/* See https://www.home-assistant.io/docs/mqtt/discovery/ */ /* See https://www.home-assistant.io/docs/mqtt/discovery/ */
payload = string("{") + payload = string("{") +
"\"~\": \"" + maintopic + "\"," + "\"~\": \"" + maintopic + "\"," +
"\"unique_id\": \"" + maintopic + "-" + configTopic + "\"," + "\"unique_id\": \"" + maintopic + "-" + configTopic + "\"," +
"\"object_id\": \"" + maintopic + "_" + configTopic + "\"," + // This used to generate the Entity ID "\"object_id\": \"" + maintopic + "_" + configTopic + "\"," + // Default entity ID; required for HA <= 2025.10
"\"default_entity_id\": \"" + component + "." + maintopic + "_" + configTopic + "\"," + // Default entity ID; required in HA >=2026.4
"\"name\": \"" + name + "\"," + "\"name\": \"" + name + "\"," +
"\"icon\": \"mdi:" + icon + "\","; "\"icon\": \"mdi:" + icon + "\",";

View File

@@ -635,7 +635,7 @@ void migrateConfiguration(void) {
CamZoom_value = false; CamZoom_value = false;
} }
else { else {
ESP_LOGE(TAG, "splitted[1]: %s", splitted[1].c_str()); // ESP_LOGI(TAG, "splitted[1]: %s", splitted[1].c_str());
CamZoom_value = alphanumericToBoolean(splitted[1]); CamZoom_value = alphanumericToBoolean(splitted[1]);
} }
CamZoom_found = true; CamZoom_found = true;
@@ -858,22 +858,22 @@ void migrateConfiguration(void) {
else { else {
configLines[CamZoom_lines] = ("CamZoom = false"); configLines[CamZoom_lines] = ("CamZoom = false");
} }
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Migrated Configfile line 'Zoom' to 'CamZoom'"); LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Migrated Configfile line 'Zoom' to 'CamZoom'");
migrated = true; migrated = true;
} }
if (CamZoomSize_lines > 0) { if (CamZoomSize_lines > 0) {
configLines[CamZoomSize_lines] = ("CamZoomSize = " + std::to_string(CamZoomSize_value)); configLines[CamZoomSize_lines] = ("CamZoomSize = " + std::to_string(CamZoomSize_value));
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Migrated Configfile line 'ZoomMode' to 'CamZoomSize'"); LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Migrated Configfile line 'ZoomMode' to 'CamZoomSize'");
migrated = true; migrated = true;
} }
if (CamZoomOffsetX_lines > 0) { if (CamZoomOffsetX_lines > 0) {
configLines[CamZoomOffsetX_lines] = ("CamZoomOffsetX = " + std::to_string(CamZoomOffsetX_value)); configLines[CamZoomOffsetX_lines] = ("CamZoomOffsetX = " + std::to_string(CamZoomOffsetX_value));
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Migrated Configfile line 'ZoomOffsetX' to 'CamZoomOffsetX'"); LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Migrated Configfile line 'ZoomOffsetX' to 'CamZoomOffsetX'");
migrated = true; migrated = true;
} }
if (CamZoomOffsetY_lines > 0) { if (CamZoomOffsetY_lines > 0) {
configLines[CamZoomOffsetY_lines] = ("CamZoomOffsetY = " + std::to_string(CamZoomOffsetY_value)); configLines[CamZoomOffsetY_lines] = ("CamZoomOffsetY = " + std::to_string(CamZoomOffsetY_value));
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Migrated Configfile line 'ZoomOffsetY' to 'CamZoomOffsetY'"); LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Migrated Configfile line 'ZoomOffsetY' to 'CamZoomOffsetY'");
migrated = true; migrated = true;
} }
} }

View File

@@ -158,7 +158,7 @@ CONFIG_CAMERA_CORE1=y
CONFIG_OV7670_SUPPORT=n CONFIG_OV7670_SUPPORT=n
CONFIG_OV7725_SUPPORT=n CONFIG_OV7725_SUPPORT=n
CONFIG_NT99141_SUPPORT=n CONFIG_NT99141_SUPPORT=n
CONFIG_OV3660_SUPPORT=n CONFIG_OV3660_SUPPORT=y
CONFIG_OV2640_SUPPORT=y CONFIG_OV2640_SUPPORT=y
CONFIG_OV5640_SUPPORT=y CONFIG_OV5640_SUPPORT=y
CONFIG_GC2145_SUPPORT=n CONFIG_GC2145_SUPPORT=n

View File

@@ -4,4 +4,4 @@ Default Value: `undefined`
Dedicated definition of the field for InfluxDB use for saving in the Influx database (e.g.: "watermeter/value"). Dedicated definition of the field for InfluxDB use for saving in the Influx database (e.g.: "watermeter/value").
!!! Note !!! Note
This parameter must be prefixed with `<NUMBER>` followed by a dot (eg. `main.Field`). `<NUMBER>` is the name of the number sequence defined in the ROI's. If you edit the config file manually, you must prefix this parameter with `<NUMBER>` followed by a dot (eg. `main.Field`). The reason is that this parameter is specific for each `<NUMBER>` (`<NUMBER>` is the name of the number sequence defined in the ROI's).

View File

@@ -4,4 +4,4 @@ Default Value: `undefined`
Field for InfluxDB v2 to use for saving. Field for InfluxDB v2 to use for saving.
!!! Note !!! Note
This parameter must be prefixed with `<NUMBER>` followed by a dot (eg. `main.Field`). `<NUMBER>` is the name of the number sequence defined in the ROI's. If you edit the config file manually, you must prefix this parameter with `<NUMBER>` followed by a dot (eg. `main.Field`). The reason is that this parameter is specific for each `<NUMBER>` (`<NUMBER>` is the name of the number sequence defined in the ROI's).

View File

@@ -10,19 +10,23 @@ Alternatively you can set the parameter `DecimalShift` to `3` so the value is co
List of supported options: List of supported options:
- `other` - `other`
- `water_m3` (uses `m^3/min` as rate) - `water_m3` (uses `m^3/h` as rate)
- `water_l` (uses `l/h` as rate, not officially supported by Homeassistant!) - `water_l` (uses `l/h` as rate) **⚠️ Not supported by Homeassistant 2025.7 and later! ⚠️**
- `water_gal` (uses `gal/h` as rate, not officially supported by Homeassistant!) - `water_gal` (uses `gal/h` as rate) **⚠️ Not supported by Homeassistant 2025.7 and later! ⚠️**
- `water_gal_min` (uses `gal/min` as rate)
- `water_ft3` (uses `ft^3/min` as rate) - `water_ft3` (uses `ft^3/min` as rate)
- `gas_m3` (uses `m^3/min` as rate) - `gas_m3` (uses `m^3/h` as rate)
- `gas_ft3` (uses `ft^3/min` as rate) - `gas_ft3` (uses `ft^3/min` as rate)
- `energy_wh` (uses `W` as rate) - `energy_wh` (uses `W` as rate)
- `energy_kwh` (uses `KW` as rate) - `energy_kwh` (uses `KW` as rate)
- `energy_mwh` (uses `MW` as rate) - `energy_mwh` (uses `MW` as rate)
- `energy_gj` (uses `GJ/h` as rate, not officially supported by Homeassistant!) - `energy_gj` (uses `GJ/h` as rate) **⚠️ Not supported by Homeassistant 2025.7 and later! ⚠️**
- `temperature_c` (uses `+C/min` as rate) - `temperature_c` (uses `+C/min` as rate)
- `temperature_f` (uses `°F/min` as rate) - `temperature_f` (uses `°F/min` as rate)
- `temperature_k` (uses `K/min` as rate) - `temperature_k` (uses `K/min` as rate)
!!! Note !!! Note
Not all options are supported by Homeassistant, see `SensorDeviceClass.VOLUME_FLOW_RATE` in [https://developers.home-assistant.io/docs/core/entity/sensor/#available-device-classes](https://developers.home-assistant.io/docs/core/entity/sensor/#available-device-classes)! Not all options are supported by Homeassistant, see `SensorDeviceClass.VOLUME_FLOW_RATE` in [https://developers.home-assistant.io/docs/core/entity/sensor/#available-device-classes](https://developers.home-assistant.io/docs/core/entity/sensor/#available-device-classes)!
!!! Warning
Since Homeassistant 2025.7, the unsupported options will no longer work, see change in Homeassistant: [Ensure MQTT sensor has a valid native unit of measurement](https://github.com/home-assistant/core/pull/146722).

View File

@@ -4,4 +4,4 @@ Default Value: `0`
The Idx number for the counter device. Can be obtained from the devices setup page on the Domoticz system. The Idx number for the counter device. Can be obtained from the devices setup page on the Domoticz system.
!!! Note !!! Note
This parameter must be prefixed with `<NUMBER>` followed by a dot (eg. `main.DomoticzIDX`). `<NUMBER>` is the name of the number sequence defined in the ROI's. If you edit the config file manually, you must prefix this parameter with `<NUMBER>` followed by a dot (eg. `main.DomoticzIDX`). The reason is that this parameter is specific for each `<NUMBER>` (`<NUMBER>` is the name of the number sequence defined in the ROI's).

View File

@@ -7,4 +7,4 @@ Allow a meter to count backwards (decreasing values).
This is unusual (it means there is a negative rate) and not wanted in most cases! This is unusual (it means there is a negative rate) and not wanted in most cases!
!!! Note !!! Note
This parameter must be prefixed with `<NUMBER>` followed by a dot (eg. `main.AllowNegativeRates`). `<NUMBER>` is the name of the number sequence defined in the ROI's. If you edit the config file manually, you must prefix this parameter with `<NUMBER>` followed by a dot (eg. `main.AllowNegativeRates`). The reason is that this parameter is specific for each `<NUMBER>` (`<NUMBER>` is the name of the number sequence defined in the ROI's).

View File

@@ -9,4 +9,4 @@ See [here](../Watermeter-specific-analog---digit-transition) for details.
Range: `6.0` .. `9.9`. Range: `6.0` .. `9.9`.
!!! Note !!! Note
This parameter must be prefixed with `<NUMBER>` followed by a dot (eg. `main.AnalogToDigitTransitionStart`). `<NUMBER>` is the name of the number sequence defined in the ROI's. If you edit the config file manually, you must prefix this parameter with `<NUMBER>` followed by a dot (eg. `main.AnalogToDigitTransitionStart`). The reason is that this parameter is specific for each `<NUMBER>` (`<NUMBER>` is the name of the number sequence defined in the ROI's).

View File

@@ -10,18 +10,18 @@ It is only applied to the last digit of the read value (See example below).
If the read value is within PreValue +/- Threshold, no further calculation is carried out and the Value/Prevalue remains at the old value. If the read value is within PreValue +/- Threshold, no further calculation is carried out and the Value/Prevalue remains at the old value.
!!! Note !!! Note
This parameter must be prefixed with `<NUMBER>` followed by a dot (eg. `main.ChangeRateThreshold`). `<NUMBER>` is the name of the number sequence defined in the ROI's. If you edit the config file manually, you must prefix this parameter with `<NUMBER>` followed by a dot (eg. `main.ChangeRateThreshold`). The reason is that this parameter is specific for each `<NUMBER>` (`<NUMBER>` is the name of the number sequence defined in the ROI's).
## Example ## Example
- Smallest ROI provides value for `0.000'x` (Eg. a water meter with 4 pointers behind the decimal point) - Smallest ROI provides value for `0.000'x` (Eg. a water meter with 4 pointers behind the decimal point)
- ChangeRateThreshold = 2 - ChangeRateThreshold = 2
#### With `Extended Resolution` **disabled** #### With `ExtendedResolution` **disabled**
PreValue: `123.456'7` -> Threshold = `+/-0.000'2`.<br> PreValue: `123.456'7` -> Threshold = `+/-0.000'2`.<br>
All changes between `123.456'5` and `123.456'9` get ignored All changes between `123.456'5` and `123.456'9` get ignored
#### With `Extended Resolution` **enabled** #### With `ExtendedResolution` **enabled**
PreValue: `123.456'78` -> Threshold = `+/-0.000'02`.<br> PreValue: `123.456'78` -> Threshold = `+/-0.000'02`.<br>
All changes between `123.456'76` and `123.456'80` get ignored. All changes between `123.456'76` and `123.456'80` get ignored.

View File

@@ -8,4 +8,4 @@ An additional consistency check.
It especially improves the zero crossing check between digits. It especially improves the zero crossing check between digits.
!!! Note !!! Note
This parameter must be prefixed with `<NUMBER>` followed by a dot (eg. `main.CheckDigitIncreaseConsistency`). `<NUMBER>` is the name of the number sequence defined in the ROI's. If you edit the config file manually, you must prefix this parameter with `<NUMBER>` followed by a dot (eg. `main.CheckDigitIncreaseConsistency`). The reason is that this parameter is specific for each `<NUMBER>` (`<NUMBER>` is the name of the number sequence defined in the ROI's).

View File

@@ -5,4 +5,4 @@ Shift the decimal separator (positiv or negativ).
Eg. to move from `m³` to `liter` (`1 m³` equals `1000 liters`), you need to set it to `+3`. Eg. to move from `m³` to `liter` (`1 m³` equals `1000 liters`), you need to set it to `+3`.
!!! Note !!! Note
This parameter must be prefixed with `<NUMBER>` followed by a dot (eg. `main.DecimalShift`). `<NUMBER>` is the name of the number sequence defined in the ROI's. If you edit the config file manually, you must prefix this parameter with `<NUMBER>` followed by a dot (eg. `main.DecimalShift`). The reason is that this parameter is specific for each `<NUMBER>` (`<NUMBER>` is the name of the number sequence defined in the ROI's).

View File

@@ -7,4 +7,4 @@ Use the decimal place of the last analog counter for increased accuracy.
This parameter is only supported on the `*-class*` and `*-const` models! See [Choosing-the-Model](../Choosing-the-Model) for details. This parameter is only supported on the `*-class*` and `*-const` models! See [Choosing-the-Model](../Choosing-the-Model) for details.
!!! Note !!! Note
This parameter must be prefixed with `<NUMBER>` followed by a dot (eg. `main.ExtendedResolution`). `<NUMBER>` is the name of the number sequence defined in the ROI's. If you edit the config file manually, you must prefix this parameter with `<NUMBER>` followed by a dot (eg. `main.ExtendedResolution`). The reason is that this parameter is specific for each `<NUMBER>` (`<NUMBER>` is the name of the number sequence defined in the ROI's).

View File

@@ -6,4 +6,4 @@ This is only relevant for models which use `N`!
See [here](../Choosing-the-Model) for details. See [here](../Choosing-the-Model) for details.
!!! Note !!! Note
This parameter must be prefixed with `<NUMBER>` followed by a dot (eg. `main.IgnoreLeadingNaN`). `<NUMBER>` is the name of the number sequence defined in the ROI's. If you edit the config file manually, you must prefix this parameter with `<NUMBER>` followed by a dot (eg. `main.IgnoreLeadingNaN`). The reason is that this parameter is specific for each `<NUMBER>` (`<NUMBER>` is the name of the number sequence defined in the ROI's).

View File

@@ -5,4 +5,4 @@ Defines if the **Change Rate** is calculated as the difference between the last
as the difference normalized to the interval (`RateChange` = difference per minute). as the difference normalized to the interval (`RateChange` = difference per minute).
!!! Note !!! Note
This parameter must be prefixed with `<NUMBER>` followed by a dot (eg. `main.MaxRateType`). `<NUMBER>` is the name of the number sequence defined in the ROI's. If you edit the config file manually, you must prefix this parameter with `<NUMBER>` followed by a dot (eg. `main.MaxRateType`). The reason is that this parameter is specific for each `<NUMBER>` (`<NUMBER>` is the name of the number sequence defined in the ROI's).

View File

@@ -6,4 +6,4 @@ Maximum allowed change between two readings, if exceeded the last reading will b
If negative rate is disallowed and no maximum rate value is set, one false high reading will lead to a period of missing measurements until the measurement reaches the previous false high reading. E.g. if the counter is at `600,00` and it's read incorrectly as` 610,00`, all measurements will be skipped until the counter reaches `610,00`. Setting the MaxRateValue to `0,05` leads to a rejection of all readings with a difference `> 0,05`, in this case `610,00`. The rejection also applies to correct readings with a difference `> 0,05`! If negative rate is disallowed and no maximum rate value is set, one false high reading will lead to a period of missing measurements until the measurement reaches the previous false high reading. E.g. if the counter is at `600,00` and it's read incorrectly as` 610,00`, all measurements will be skipped until the counter reaches `610,00`. Setting the MaxRateValue to `0,05` leads to a rejection of all readings with a difference `> 0,05`, in this case `610,00`. The rejection also applies to correct readings with a difference `> 0,05`!
!!! Note !!! Note
This parameter must be prefixed with `<NUMBER>` followed by a dot (eg. `main.MaxRateValue`). `<NUMBER>` is the name of the number sequence defined in the ROI's. If you edit the config file manually, you must prefix this parameter with `<NUMBER>` followed by a dot (eg. `main.MaxRateValue`). The reason is that this parameter is specific for each `<NUMBER>` (`<NUMBER>` is the name of the number sequence defined in the ROI's).

Binary file not shown.

Binary file not shown.

View File

@@ -156,6 +156,7 @@ The following settings are only used for easier setup, they are <b>not</b> persi
<input type="checkbox" id="showall" name="showall" value="1" onclick="draw()" checked tabindex=9><label for="showall"> Show all ROIs</label><br> <input type="checkbox" id="showall" name="showall" value="1" onclick="draw()" checked tabindex=9><label for="showall"> Show all ROIs</label><br>
<input type="checkbox" id="lockAspectRatio" name="lockAspectRatio" value="1" onclick="changelockAspectRatio()" checked tabindex=6><label for="lockAspectRatio"> Lock aspect ratio </label><br> <input type="checkbox" id="lockAspectRatio" name="lockAspectRatio" value="1" onclick="changelockAspectRatio()" checked tabindex=6><label for="lockAspectRatio"> Lock aspect ratio </label><br>
<input type="checkbox" id="lockSizes" name="lockSizes" value="1" onclick="changelockSizes()" checked tabindex=7><label for="lockSizes"> Synchronize y, Δx and Δy between ROIs</label><br> <input type="checkbox" id="lockSizes" name="lockSizes" value="1" onclick="changelockSizes()" checked tabindex=7><label for="lockSizes"> Synchronize y, Δx and Δy between ROIs</label><br>
<input type="checkbox" id="drawFromCenter" name="drawFromCenter" value="1" onclick="changeDrawFromCenter()" checked tabindex=8><label for="drawFromCenter"> Draw from center</label><br>
<hr> <hr>
<table> <table>
@@ -196,6 +197,7 @@ The following settings are only used for easier setup, they are <b>not</b> persi
enhanceCon = false, enhanceCon = false,
lockAspectRatio = true, lockAspectRatio = true,
lockSizes = false, lockSizes = false,
drawFromCenter = true,
domainname = getDomainname(); domainname = getDomainname();
function doReboot() { function doReboot() {
@@ -319,6 +321,10 @@ The following settings are only used for easier setup, they are <b>not</b> persi
UpdateROIs(); UpdateROIs();
} }
function changeDrawFromCenter() {
drawFromCenter = document.getElementById("drawFromCenter").checked;
}
function changeCCW() { function changeCCW() {
var sel = document.getElementById("Numbers_value1"); var sel = document.getElementById("Numbers_value1");
var _number = sel.options[sel.selectedIndex].text; var _number = sel.options[sel.selectedIndex].text;
@@ -800,6 +806,10 @@ The following settings are only used for easier setup, they are <b>not</b> persi
zw = getCoords(this) zw = getCoords(this)
rect.startX = e.pageX - zw.left; rect.startX = e.pageX - zw.left;
rect.startY = e.pageY - zw.top; rect.startY = e.pageY - zw.top;
if (drawFromCenter) {
rect.centerX = rect.startX;
rect.centerY = rect.startY;
}
document.getElementById("refx").value = rect.startX; document.getElementById("refx").value = rect.startX;
document.getElementById("refy").value = rect.startY; document.getElementById("refy").value = rect.startY;
drag = true; drag = true;
@@ -822,16 +832,33 @@ The following settings are only used for easier setup, they are <b>not</b> persi
} }
function mouseMove(e) { function mouseMove(e) {
const mouseX = e.pageX - zw.left;
const mouseY = e.pageY - zw.top;
if (drag) { if (drag) {
zw = getCoords(this) zw = getCoords(this)
if (lockAspectRatio) { if (drawFromCenter) {
rect.h = (e.pageY - zw.top) - rect.startY; if (lockAspectRatio) {
rect.w = Math.round(rect.h * ROIInfo[aktindex]["ar"]); rect.h = Math.abs(mouseY - rect.centerY) * 2;
} rect.w = Math.round(rect.h * ROIInfo[aktindex]["ar"]);
else { } else {
rect.w = (e.pageX - zw.left) - rect.startX; rect.w = Math.abs(mouseX - rect.centerX) * 2;
rect.h = (e.pageY - zw.top) - rect.startY; rect.h = Math.abs(mouseY - rect.centerY) * 2;
}
rect.startX = rect.centerX - rect.w / 2;
rect.startY = rect.centerY - rect.h / 2;
document.getElementById("refx").value = Math.round(rect.startX);
document.getElementById("refy").value = Math.round(rect.startY);
} else {
if (lockAspectRatio) {
rect.h = mouseY - rect.startY;
rect.w = Math.round(rect.h * ROIInfo[aktindex]["ar"]);
} else {
rect.w = mouseX - rect.startX;
rect.h = mouseY - rect.startY;
}
} }
document.getElementById("refdx").value = rect.w; document.getElementById("refdx").value = rect.w;
document.getElementById("refdy").value = rect.h; document.getElementById("refdy").value = rect.h;
@@ -843,8 +870,8 @@ The following settings are only used for easier setup, they are <b>not</b> persi
var context = canvas.getContext('2d'); var context = canvas.getContext('2d');
zw = getCoords(this); zw = getCoords(this);
x = e.pageX - zw.left; x = mouseX;
y = e.pageY - zw.top; y = mouseY;
context.lineWidth = 2; context.lineWidth = 2;
context.strokeStyle = "#00FF00"; context.strokeStyle = "#00FF00";

View File

@@ -1183,15 +1183,16 @@
<select class="select_large" id="MQTT_MeterType_value1"> <!-- See https://developers.home-assistant.io/docs/core/entity/sensor/#available-device-classes --> <select class="select_large" id="MQTT_MeterType_value1"> <!-- See https://developers.home-assistant.io/docs/core/entity/sensor/#available-device-classes -->
<option value="other" selected>Other (no Units)</option> <option value="other" selected>Other (no Units)</option>
<option value="water_m3">Watermeter (Value: m³, Rate: m³/h)</option> <option value="water_m3">Watermeter (Value: m³, Rate: m³/h)</option>
<option value="water_l">Watermeter (Value: l, Rate: l/h) *Not officially supported by Homeassistant!*</option> <option value="water_l">Watermeter (Value: l, Rate: l/h) ⚠️ Not supported by Homeassistant 2025.7 and later! ⚠️</option>
<option value="water_gal">Watermeter (Value: gal, Rate: gal/h) *Not officially supported by Homeassistant!*</option> <option value="water_gal">Watermeter (Value: gal, Rate: gal/h) ⚠️ Not supported by Homeassistant 2025.7 and later! ⚠️</option>
<option value="water_gal_min">Watermeter (Value: gal, Rate: gal/min)</option>
<option value="water_ft3">Watermeter (Value: ft³, Rate: ft³/min)</option> <option value="water_ft3">Watermeter (Value: ft³, Rate: ft³/min)</option>
<option value="gas_m3">Gasmeter (Value: m³, Rate: m³/h)</option> <option value="gas_m3">Gasmeter (Value: m³, Rate: m³/h)</option>
<option value="gas_ft3">Gasmeter (Value: ft³, Rate: ft³/min)</option> <option value="gas_ft3">Gasmeter (Value: ft³, Rate: ft³/min)</option>
<option value="energy_wh">Energymeter (Value: Wh, Rate: W)</option> <option value="energy_wh">Energymeter (Value: Wh, Rate: W)</option>
<option value="energy_kwh">Energymeter (Value: kWh, Rate: kW)</option> <option value="energy_kwh">Energymeter (Value: kWh, Rate: kW)</option>
<option value="energy_mwh">Energymeter (Value: MWh, Rate: MW)</option> <option value="energy_mwh">Energymeter (Value: MWh, Rate: MW)</option>
<option value="energy_gj">Energymeter (Value: GJ, Rate: GJ/h) *Not officially supported by Homeassistant!*</option> <option value="energy_gj">Energymeter (Value: GJ, Rate: GJ/h) ⚠️ Not supported by Homeassistant 2025.7 and later! ⚠️</option>
<option value="temperature_c">Thermometer (Value: °C, Rate: °C/min)</option> <option value="temperature_c">Thermometer (Value: °C, Rate: °C/min)</option>
<option value="temperature_c">Thermometer (Value: °F, Rate: °F/min)</option> <option value="temperature_c">Thermometer (Value: °F, Rate: °F/min)</option>
<option value="temperature_c">Thermometer (Value: K, Rate: K/min)</option> <option value="temperature_c">Thermometer (Value: K, Rate: K/min)</option>
@@ -2676,7 +2677,19 @@ function saveTextAsFile() {
WriteConfigININew(); WriteConfigININew();
SaveConfigToServer(domainname); SaveConfigToServer(domainname);
firework.launch('Configuration saved. It will get applied after the next reboot!<br><br>\n<a id="reboot_button" onclick="doReboot()">reboot now</a>', 'success', 5000); if(window.location.hash) {
var hash = window.location.hash.substring(1); //Puts hash in variable, and removes the # character
if(hash == 'description') {
firework.launch('Configuration saved.', 'success', 2000);
}
else {
firework.launch('Configuration saved. It will get applied after the next reboot!<br><br>\n<a id="reboot_button" onclick="doReboot()">reboot now</a>', 'success', 5000);
}
}
else {
firework.launch('Configuration saved. It will get applied after the next reboot!<br><br>\n<a id="reboot_button" onclick="doReboot()">reboot now</a>', 'success', 5000);
}
if (changeCamValue == 1) { if (changeCamValue == 1) {
camSettingsSet(); camSettingsSet();
@@ -3331,7 +3344,7 @@ function openDescription() {
if(hash == 'description') { if(hash == 'description') {
document.getElementById("desc_details").open = true; document.getElementById("desc_details").open = true;
document.getElementById("reboot").style.display = "none"; // document.getElementById("reboot").style.display = "none";
document.getElementById("reboot_text").style.display = "none"; document.getElementById("reboot_text").style.display = "none";
} }
} }