Compare commits

..

14 Commits

Author SHA1 Message Date
CaCO3
74e150cfab clarify the parameter prefix 2025-04-22 23:58:44 +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
CaCO3
f06ef7b80e remove msg_id in the log, it is of no use (#3678) 2025-03-30 20:58:20 +02:00
Erik
962a674058 Refine Home Assistant MQTT Auto Discovery (#3659)
Add a proper device_class (duration) to "uptime"
2025-03-29 13:28:23 +01:00
SybexX
c57cd83948 Update README.md 2025-03-26 23:07:37 +01:00
The Random DIY
6991c41060 README updated with missed English translation (#3673)
* README updated with missed English translation

* Readme updated
2025-03-26 22:53:16 +01:00
SybexX
8bb274cd84 Merge pull request #3668 from nechry/main
Update NUMBER.ChangeRateThreshold.md
2025-03-24 03:19:41 +01:00
SybexX
168ec5b485 Update edit_config_template.html 2025-03-22 18:07:56 +01:00
Jean-François Auger
7a0a34e32e Update NUMBER.ChangeRateThreshold.md 2025-03-22 17:28:45 +01:00
45 changed files with 303 additions and 8046 deletions

View File

@@ -1,6 +1,10 @@
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:
#########################################################################################
@@ -304,7 +308,7 @@ jobs:
prepare-release:
runs-on: ubuntu-latest
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
permissions:
@@ -406,7 +410,7 @@ jobs:
#########################################################################################
# Make sure to also update update-webinstaller.yml!
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]
environment:
name: github-pages
@@ -444,13 +448,13 @@ jobs:
sed -i 's/$VERSION/${{ steps.last_release.outputs.tag_name }}/g' webinstaller/manifest.json
- name: Setup Pages
uses: actions/configure-pages@v4
uses: actions/configure-pages@v5
- name: Upload artifact
uses: actions/upload-pages-artifact@v2
uses: actions/upload-pages-artifact@v3
with:
path: 'webinstaller'
- name: Deploy to GitHub Pages
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:
comment:
runs-on: ubuntu-20.04
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

View File

@@ -4,7 +4,7 @@
```
git clone https://github.com/jomjol/AI-on-the-edge-device.git
cd AI-on-the-edge-device
git checkout rolling
git checkout main
git submodule update --init
```
@@ -12,10 +12,10 @@ git submodule update --init
```
cd /components/submodule-name (e.g. tflite-micro-example)
git checkout VERSION (e.g. HASH of latest tflite-micro-example build)
cd ../../ (auf Ebene von code)
cd ../../ (at the code level)
git submodule update --init
```
Evt. muss man vorher noch einige Verzeichnisse in compenents von Hand löschen, da sie beim checkout nicht gelöscht wurden (vor update -- init)
You may need to manually delete some directories in the 'components' folder beforehand, as they were not deleted during checkout (before update -- init)
## Build and Flash within terminal
See further down to build it within an IDE.
@@ -51,7 +51,7 @@ pio device monitor -p /dev/ttyUSB0
```
git clone https://github.com/jomjol/AI-on-the-edge-device.git
cd AI-on-the-edge-device
git checkout rolling
git checkout main
git submodule update --init
```

View File

@@ -1,7 +0,0 @@
FILE(GLOB_RECURSE app_sources ${CMAKE_CURRENT_SOURCE_DIR}/*.*)
idf_component_register(SRCS ${app_sources}
INCLUDE_DIRS "."
REQUIRES esp_eth nvs_flash wpa_supplicant jomjol_wlan jomjol_helper jomjol_mqtt esp_netif)

View File

@@ -1,210 +0,0 @@
#if defined(BOARD_ESP32_S3_ALEKSEI)
#include "connect_lan.h"
#include <string.h>
#include <stdlib.h>
#include <fstream>
#include <vector>
#include <sstream>
#include <iostream>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/event_groups.h"
#include "driver/gpio.h"
#include "esp_system.h"
#include "esp_wifi.h"
#include "esp_wnm.h"
#include "esp_rrm.h"
#include "esp_mbo.h"
#include "esp_mac.h"
#include "esp_netif.h"
#include <netdb.h>
#include "esp_log.h"
#include "nvs_flash.h"
#include "lwip/err.h"
#include "lwip/sys.h"
#ifdef ENABLE_MQTT
#include "interface_mqtt.h"
#endif //ENABLE_MQTT
#include "ClassLogFile.h"
#include "read_lanini.h"
#include "Helper.h"
#include "statusled.h"
#include "../../include/defines.h"
#if (ESP_IDF_VERSION_MAJOR >= 5)
#include "soc/periph_defs.h"
#include "esp_private/periph_ctrl.h"
#include "soc/gpio_sig_map.h"
#include "soc/gpio_periph.h"
#include "soc/io_mux_reg.h"
#include "esp_rom_gpio.h"
#define gpio_pad_select_gpio esp_rom_gpio_pad_select_gpio
#define gpio_matrix_in(a,b,c) esp_rom_gpio_connect_in_signal(a,b,c)
#define gpio_matrix_out(a,b,c,d) esp_rom_gpio_connect_out_signal(a,b,c,d)
#define ets_delay_us(a) esp_rom_delay_us(a)
#endif
#include "../esp-protocols/components/mdns/include/mdns.h"
#include <driver/spi_master.h>
#include <esp_eth.h>
#include <esp_netif.h>
static const char *TAG = "LAN";
extern bool WIFIConnected;
static int LanReconnectCnt = 0;
std::string* getLanIPAddress()
{
return &wlan_config.ipaddress;
}
static void eth_event_handler(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data)
{
if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START)
{
WIFIConnected = false;
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Ethernet Started");
}
else if (event_base == ETH_EVENT && event_id == ETHERNET_EVENT_DISCONNECTED)
{
LogFile.WriteToFile(ESP_LOG_WARN, TAG, "Ethernet Link Down");
// Optionally, try to reconnect or handle fallback LED:
StatusLED(WLAN_CONN, 1, false);
LanReconnectCnt++;
WIFIConnected = false;
}
else if (event_base == ETH_EVENT && event_id == ETHERNET_EVENT_CONNECTED)
{
uint8_t mac_addr[6] = {0};
esp_eth_handle_t eth_handle = *(esp_eth_handle_t *)event_data;
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Ethernet Link Up");
esp_eth_ioctl(eth_handle, ETH_CMD_G_MAC_ADDR, mac_addr);
ESP_LOGI(TAG, "Ethernet HW Addr %02x:%02x:%02x:%02x:%02x:%02x",
mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]);
}
else if (event_base == ETH_EVENT && event_id == ETHERNET_EVENT_STOP) {
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Ethernet Stopped");
WIFIConnected = false;
}
}
static void got_ip_event_handler(void *arg, esp_event_base_t event_base,
int32_t event_id, void *event_data)
{
WIFIConnected = true;
LanReconnectCnt = 0;
ip_event_got_ip_t* event = (ip_event_got_ip_t*) event_data;
wlan_config.ipaddress = std::string(ip4addr_ntoa((const ip4_addr*) &event->ip_info.ip));
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Assigned IP: " + wlan_config.ipaddress);
#ifdef ENABLE_MQTT
if (getMQTTisEnabled()) {
vTaskDelay(5000 / portTICK_PERIOD_MS);
MQTT_Init(); // Init when WIFI is getting connected
}
#endif //ENABLE_MQTT
// LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Assigned IP: " + WIFIConnected);
// LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Assigned IP: " + getWIFIisConnected());
}
esp_eth_handle_t eth_handle = NULL;
esp_netif_t *eth_netif = NULL;
int lan_init(void)
{
esp_err_t retval = esp_netif_init();
if (retval != ESP_OK) {
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "esp_netif_init: Error: " + std::to_string(retval));
return retval;
}
int retVal = esp_event_loop_create_default();
if (retVal != ESP_OK && retVal != ESP_ERR_INVALID_STATE) {
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "esp_event_loop_create_default, Error");
return retVal;
}
gpio_set_direction(ETH_ENABLE, GPIO_MODE_OUTPUT);
gpio_set_level(ETH_ENABLE, 1);
gpio_set_direction(ETH_INT, GPIO_MODE_INPUT);
gpio_set_pull_mode(ETH_INT, GPIO_PULLUP_ONLY);
esp_log_level_set("netif", ESP_LOG_DEBUG);
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "SPI init");
// 1) SPI bus init
spi_bus_config_t buscfg = { 0 };
buscfg.mosi_io_num = ETH_MOSI;
buscfg.miso_io_num = ETH_MISO;
buscfg.sclk_io_num = ETH_CLK;
ESP_ERROR_CHECK(spi_bus_initialize(W5500_SPI_HOST, &buscfg, SPI_DMA_CH_AUTO));
// 2) Prepare a `spi_device_interface_config_t` but DO NOT call spi_bus_add_device manually
spi_device_interface_config_t devcfg = {
.mode = 0, // SPI mode 0
.clock_speed_hz = 40 * 1000 * 1000, // 20MHz
.spics_io_num = ETH_CS,
.queue_size = 30,
// the rest zero-initialized
};
eth_w5500_config_t w5500_config = ETH_W5500_DEFAULT_CONFIG(W5500_SPI_HOST, &devcfg);
w5500_config.int_gpio_num = ETH_INT;
// 4) Standard MAC/PHY config
eth_mac_config_t mac_config = ETH_MAC_DEFAULT_CONFIG();
esp_eth_mac_t *mac = esp_eth_mac_new_w5500(&w5500_config, &mac_config);
eth_phy_config_t phy_config = ETH_PHY_DEFAULT_CONFIG();
phy_config.phy_addr = 1; // typical W5500
esp_eth_phy_t *phy = esp_eth_phy_new_w5500(&phy_config);
esp_eth_config_t eth_config = ETH_DEFAULT_CONFIG(mac, phy);
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Driver install");
ESP_ERROR_CHECK(esp_eth_driver_install(&eth_config, &eth_handle));
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Driver installed");
uint8_t base_mac_addr[6];
esp_err_t ret = esp_efuse_mac_get_default(base_mac_addr);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "Failed to get efuse base MAC, error=0x%x", ret);
}
uint8_t local_mac[6];
esp_derive_local_mac(local_mac, base_mac_addr);
ret = esp_eth_ioctl(eth_handle, ETH_CMD_S_MAC_ADDR, local_mac);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "Failed to set W5500 MAC, error=0x%x", ret);
}
// 5) Attach netif + start
esp_netif_config_t netif_cfg = ESP_NETIF_DEFAULT_ETH();
eth_netif = esp_netif_new(&netif_cfg);
// Register event handlers
ESP_ERROR_CHECK(esp_event_handler_register(
ETH_EVENT, ESP_EVENT_ANY_ID,
&eth_event_handler, NULL));
ESP_ERROR_CHECK(esp_event_handler_register(
IP_EVENT, IP_EVENT_ETH_GOT_IP,
&got_ip_event_handler, NULL));
esp_netif_attach(eth_netif, esp_eth_new_netif_glue(eth_handle));
esp_eth_start(eth_handle);
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "W5500 Ethernet init done");
return ESP_OK;
}
#endif

View File

@@ -1,20 +0,0 @@
#if defined(BOARD_ESP32_S3_ALEKSEI)
#pragma once
#ifndef CONNECT_LAN_H
#define CONNECT_LAN_H
#include <string>
// #include "connect_wlan.h"
// int wifi_init_sta(void);
std::string* getLanIPAddress();
// int get_WIFI_RSSI();
std::string* getLanHostname();
bool getLanIsConnected();
void LanDestroy();
int lan_init();
#endif //CONNECT_WLAN_H
#endif

View File

@@ -1,248 +0,0 @@
#if defined(BOARD_ESP32_S3_ALEKSEI)
#include "read_lanini.h"
#include "Helper.h"
#include "connect_lan.h"
#include <fstream>
#include <string>
#include <vector>
#include <sstream>
#include <iostream>
#include <string.h>
#include "esp_log.h"
#include "ClassLogFile.h"
#include "../../include/defines.h"
static const char *TAG = "LANINI";
std::vector<string> ZerlegeZeileLAN(std::string input, std::string _delimiter = "")
{
std::vector<string> Output;
std::string delimiter = " =,";
if (_delimiter.length() > 0){
delimiter = _delimiter;
}
input = trim(input, delimiter);
size_t pos = findDelimiterPos(input, delimiter);
std::string token;
if (pos != std::string::npos) // splitted only up to first equal sign !!! Special case for LAN.ini
{
token = input.substr(0, pos);
token = trim(token, delimiter);
Output.push_back(token);
input.erase(0, pos + 1);
input = trim(input, delimiter);
}
Output.push_back(input);
return Output;
}
int LoadLanFromFile(std::string fn)
{
std::string line = "";
std::string tmp = "";
std::vector<string> splitted;
fn = FormatFileName(fn);
FILE* pFile = fopen(fn.c_str(), "r");
if (pFile == NULL) {
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Unable to open file (read). Device init aborted!");
return -1;
}
ESP_LOGD(TAG, "LoadLanFromFile: lan.ini opened");
char zw[256];
if (fgets(zw, sizeof(zw), pFile) == NULL) {
line = "";
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "file opened, but empty or content not readable. Device init aborted!");
fclose(pFile);
return -1;
}
else {
line = std::string(zw);
}
while ((line.size() > 0) || !(feof(pFile)))
{
//ESP_LOGD(TAG, "line: %s", line.c_str());
if (line[0] != ';') { // Skip lines which starts with ';'
splitted = ZerlegeZeileLAN(line, "=");
splitted[0] = trim(splitted[0], " ");
if ((splitted.size() > 1) && (toUpper(splitted[0]) == "HOSTNAME")){
tmp = trim(splitted[1]);
if ((tmp[0] == '"') && (tmp[tmp.length()-1] == '"')){
tmp = tmp.substr(1, tmp.length()-2);
}
wlan_config.hostname = tmp;
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Hostname: " + wlan_config.hostname);
}
else if ((splitted.size() > 1) && (toUpper(splitted[0]) == "IP")){
tmp = splitted[1];
if ((tmp[0] == '"') && (tmp[tmp.length()-1] == '"')){
tmp = tmp.substr(1, tmp.length()-2);
}
wlan_config.ipaddress = tmp;
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "IP-Address: " + wlan_config.ipaddress);
}
else if ((splitted.size() > 1) && (toUpper(splitted[0]) == "GATEWAY")){
tmp = splitted[1];
if ((tmp[0] == '"') && (tmp[tmp.length()-1] == '"')){
tmp = tmp.substr(1, tmp.length()-2);
}
wlan_config.gateway = tmp;
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Gateway: " + wlan_config.gateway);
}
else if ((splitted.size() > 1) && (toUpper(splitted[0]) == "NETMASK")){
tmp = splitted[1];
if ((tmp[0] == '"') && (tmp[tmp.length()-1] == '"')){
tmp = tmp.substr(1, tmp.length()-2);
}
wlan_config.netmask = tmp;
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Netmask: " + wlan_config.netmask);
}
else if ((splitted.size() > 1) && (toUpper(splitted[0]) == "DNS")){
tmp = splitted[1];
if ((tmp[0] == '"') && (tmp[tmp.length()-1] == '"')){
tmp = tmp.substr(1, tmp.length()-2);
}
wlan_config.dns = tmp;
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "DNS: " + wlan_config.dns);
}
else if ((splitted.size() > 1) && (toUpper(splitted[0]) == "HTTP_USERNAME")){
tmp = splitted[1];
if ((tmp[0] == '"') && (tmp[tmp.length()-1] == '"')){
tmp = tmp.substr(1, tmp.length()-2);
}
wlan_config.http_username = tmp;
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "HTTP_USERNAME: " + wlan_config.http_username);
}
else if ((splitted.size() > 1) && (toUpper(splitted[0]) == "HTTP_PASSWORD")){
tmp = splitted[1];
if ((tmp[0] == '"') && (tmp[tmp.length()-1] == '"')){
tmp = tmp.substr(1, tmp.length()-2);
}
wlan_config.http_password = tmp;
#ifndef __HIDE_PASSWORD
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "HTTP_PASSWORD: " + wlan_config.http_password);
#else
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "HTTP_PASSWORD: XXXXXXXX");
#endif
}
}
/* read next line */
if (fgets(zw, sizeof(zw), pFile) == NULL) {
line = "";
}
else {
line = std::string(zw);
}
}
fclose(pFile);
return 0;
}
bool ChangeLanHostName(std::string fn, std::string _newhostname)
{
if (_newhostname == wlan_config.hostname)
return false;
std::string line = "";
std::vector<string> splitted;
std::vector<string> neuesfile;
bool found = false;
FILE* pFile = NULL;
fn = FormatFileName(fn);
pFile = fopen(fn.c_str(), "r");
if (pFile == NULL) {
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "ChangeHostName: Unable to open file lan.ini (read)");
return false;
}
ESP_LOGD(TAG, "ChangeHostName: lan.ini opened");
char zw[256];
if (fgets(zw, sizeof(zw), pFile) == NULL) {
line = "";
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "ChangeHostName: File opened, but empty or content not readable");
return false;
}
else {
line = std::string(zw);
}
while ((line.size() > 0) || !(feof(pFile)))
{
//ESP_LOGD(TAG, "ChangeHostName: line: %s", line.c_str());
splitted = ZerlegeZeileLAN(line, "=");
splitted[0] = trim(splitted[0], " ");
if ((splitted.size() > 1) && ((toUpper(splitted[0]) == "HOSTNAME") || (toUpper(splitted[0]) == ";HOSTNAME"))){
line = "hostname = \"" + _newhostname + "\"\n";
found = true;
}
neuesfile.push_back(line);
if (fgets(zw, sizeof(zw), pFile) == NULL)
{
line = "";
}
else
{
line = std::string(zw);
}
}
if (!found)
{
line = "\n;++++++++++++++++++++++++++++++++++\n";
line += "; Hostname: Name of device in network\n";
line += "; This parameter can be configured via WebUI configuration\n";
line += "; Default: \"watermeter\", if nothing is configured\n\n";
line = "hostname = \"" + _newhostname + "\"\n";
neuesfile.push_back(line);
}
fclose(pFile);
pFile = fopen(fn.c_str(), "w+");
if (pFile == NULL) {
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "ChangeHostName: Unable to open file wlan.ini (write)");
return false;
}
for (int i = 0; i < neuesfile.size(); ++i)
{
//ESP_LOGD(TAG, "%s", neuesfile[i].c_str());
fputs(neuesfile[i].c_str(), pFile);
}
fclose(pFile);
ESP_LOGD(TAG, "ChangeLanHostName done");
return true;
}
#endif

View File

@@ -1,19 +0,0 @@
#if defined(BOARD_ESP32_S3_ALEKSEI)
#pragma once
#ifndef READ_LANINI_H
#define READ_LANINI_H
#include <string>
#include "read_wlanini.h"
extern struct wlan_config wlan_config;
int LoadLanFromFile(std::string fn);
bool ChangeLanHostName(std::string fn, std::string _newhostname);
#endif //READ_WLANINI_H
#endif

View File

@@ -244,10 +244,6 @@ bool CCamera::getCameraInitSuccessful(void)
esp_err_t CCamera::setSensorDatenFromCCstatus(void)
{
#if defined(BOARD_ESP32_S3_ALEKSEI)
esp_camera_deinit();
ESP_ERROR_CHECK( esp_camera_init(&camera_config) );
#endif
sensor_t *s = esp_camera_sensor_get();
if (s != NULL)
@@ -1015,7 +1011,7 @@ esp_err_t CCamera::CaptureToStream(httpd_req_t *req, bool FlashlightOn)
vTaskDelay(xDelay);
}
}
// httpd_resp_send_chunk(req, NULL, 0); //
LEDOnOff(false); // Status-LED off
LightOnOff(false); // Flash-LED off

View File

@@ -230,10 +230,6 @@ void ClassFlowControll::setAutoStartInterval(long &_interval)
_interval = AutoInterval * 60 * 1000; // AutoInterval: minutes -> ms
}
void ClassFlowControll::setSleepWhileIdle(bool& _sleepwhileidle){
_sleepwhileidle = SleepWhileIdle;
}
ClassFlow* ClassFlowControll::CreateClassFlow(std::string _type)
{
ClassFlow* cfc = NULL;
@@ -579,10 +575,6 @@ bool ClassFlowControll::ReadParameter(FILE* pfile, string& aktparamgraph)
}
}
if ((toUpper(splitted[0]) == "SLEEPWHILEIDLE") && (splitted.size() > 1)) {
SleepWhileIdle = alphanumericToBoolean(splitted[1]);
}
if ((toUpper(splitted[0]) == "DATALOGACTIVE") && (splitted.size() > 1)) {
LogFile.SetDataLogToSD(alphanumericToBoolean(splitted[1]));
}

View File

@@ -37,7 +37,6 @@ protected:
bool AutoStart;
float AutoInterval;
bool SleepWhileIdle;
void SetInitialParameter(void);
std::string aktstatusWithTime;
std::string aktstatus;
@@ -73,7 +72,6 @@ public:
bool getIsAutoStart();
void setAutoStartInterval(long &_interval);
void setSleepWhileIdle(bool& _sleepwhileidle);
std::string* getActStatusWithTime();
std::string* getActStatus();

View File

@@ -43,7 +43,6 @@ bool bTaskAutoFlowCreated = false;
bool flowisrunning = false;
long auto_interval = 0;
bool sleep_while_idle = false;
bool autostartIsEnabled = false;
int countRounds = 0;
@@ -1660,7 +1659,6 @@ void task_autodoFlow(void *pvParameter)
doInit();
flowctrl.setAutoStartInterval(auto_interval);
flowctrl.setSleepWhileIdle(sleep_while_idle);
autostartIsEnabled = flowctrl.getIsAutoStart();
if (isSetupModusActive())
@@ -1741,20 +1739,9 @@ void task_autodoFlow(void *pvParameter)
if (auto_interval > fr_delta_ms)
{
if(sleep_while_idle){
vTaskDelay(10000 / portTICK_PERIOD_MS);//A little more time so the user can finish config
fr_delta_ms = (esp_timer_get_time() - fr_start) / 1000;
if (auto_interval > fr_delta_ms){
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Deep sleep for " + std::to_string(auto_interval - fr_delta_ms));
esp_sleep_enable_timer_wakeup((auto_interval - fr_delta_ms) * 1000); // Time in microseconds
esp_deep_sleep_start();
}
}else{
const TickType_t xDelay = (auto_interval - fr_delta_ms) / portTICK_PERIOD_MS;
ESP_LOGD(TAG, "Autoflow: sleep for: %ldms", (long)xDelay);
vTaskDelay(xDelay);
}
const TickType_t xDelay = (auto_interval - fr_delta_ms) / portTICK_PERIOD_MS;
ESP_LOGD(TAG, "Autoflow: sleep for: %ldms", (long)xDelay);
vTaskDelay(xDelay);
}
}

View File

@@ -644,19 +644,11 @@ string toLower(string in)
}
// CPU Temp
#if defined(BOARD_ESP32_S3_ALEKSEI) // ESP32s3 hat die Funktion nicht
float temperatureRead()
{
return 0.0;
}
#else
extern "C" uint8_t temprature_sens_read();
float temperatureRead()
{
return (temprature_sens_read() - 32) / 1.8;
}
#endif
time_t addDays(time_t startTime, int days)
{

View File

@@ -112,8 +112,8 @@ bool SDCardCheckFolderFilePresence()
}
/* check if file exists: wlan.ini */
if (stat("/sdcard/wlan.ini", &sb) != 0 and stat("/sdcard/lan.ini", &sb) != 0) {
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Folder/file check: File /wlan.ini and /lan.ini not found");
if (stat("/sdcard/wlan.ini", &sb) != 0) {
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Folder/file check: File /wlan.ini not found");
bRetval = false;
}

View File

@@ -85,7 +85,7 @@ bool MQTTPublish(std::string _key, std::string _content, int qos, bool retained_
_content.append("..");
}
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "Published topic: " + _key + ", content: " + _content + " (msg_id=" + std::to_string(msg_id) + ")");
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "Published topic: " + _key + ", content: " + _content);
return true;
}
else {
@@ -465,7 +465,7 @@ void MQTTconnected(){
if (subscribeFunktionMap != NULL) {
for(std::map<std::string, std::function<bool(std::string, char*, int)>>::iterator it = subscribeFunktionMap->begin(); it != subscribeFunktionMap->end(); ++it) {
int msg_id = esp_mqtt_client_subscribe(client, it->first.c_str(), 0);
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "topic " + it->first + " subscribe successful, msg_id=" + std::to_string(msg_id));
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "topic " + it->first + " subscribe successful");
}
}

View File

@@ -174,14 +174,14 @@ bool MQTThomeassistantDiscovery(int qos) {
int aFreeInternalHeapSizeBefore = heap_caps_get_free_size(MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
// Group | Field | User Friendly Name | Icon | Unit | Device Class | State Class | Entity Category
allSendsSuccessed |= sendHomeAssistantDiscoveryTopic("", "uptime", "Uptime", "clock-time-eight-outline", "s", "", "", "diagnostic", qos);
allSendsSuccessed |= sendHomeAssistantDiscoveryTopic("", "uptime", "Uptime", "progress-clock", "s", "duration", "measurement", "diagnostic", qos);
allSendsSuccessed |= sendHomeAssistantDiscoveryTopic("", "MAC", "MAC Address", "network-outline", "", "", "", "diagnostic", qos);
allSendsSuccessed |= sendHomeAssistantDiscoveryTopic("", "fwVersion", "Firmware Version", "application-outline", "", "", "", "diagnostic", qos);
allSendsSuccessed |= sendHomeAssistantDiscoveryTopic("", "hostname", "Hostname", "network-outline", "", "", "", "diagnostic", qos);
allSendsSuccessed |= sendHomeAssistantDiscoveryTopic("", "freeMem", "Free Memory", "memory", "B", "", "measurement", "diagnostic", qos);
allSendsSuccessed |= sendHomeAssistantDiscoveryTopic("", "wifiRSSI", "Wi-Fi RSSI", "wifi", "dBm", "signal_strength", "", "diagnostic", qos);
allSendsSuccessed |= sendHomeAssistantDiscoveryTopic("", "CPUtemp", "CPU Temperature", "thermometer", "°C", "temperature", "measurement", "diagnostic", qos);
allSendsSuccessed |= sendHomeAssistantDiscoveryTopic("", "interval", "Interval", "clock-time-eight-outline", "min", "" , "measurement", "diagnostic", qos);
allSendsSuccessed |= sendHomeAssistantDiscoveryTopic("", "interval", "Interval", "clock-time-eight-outline", "min", "", "measurement", "diagnostic", qos);
allSendsSuccessed |= sendHomeAssistantDiscoveryTopic("", "IP", "IP", "network-outline", "", "", "", "diagnostic", qos);
allSendsSuccessed |= sendHomeAssistantDiscoveryTopic("", "status", "Status", "list-status", "", "", "", "diagnostic", qos);
allSendsSuccessed |= sendHomeAssistantDiscoveryTopic("", "flowstart", "Manual Flow Start", "timer-play-outline", "", "", "", "", qos);

View File

@@ -55,7 +55,7 @@
static const char *TAG = "WIFI";
static bool APWithBetterRSSI = false;
bool WIFIConnected = false;
static bool WIFIConnected = false;
static int WIFIReconnectCnt = 0;
esp_netif_t *my_sta;

View File

@@ -14,8 +14,6 @@ std::string* getHostname();
bool getWIFIisConnected();
void WIFIDestroy();
extern bool WIFIConnected;
#if (defined WLAN_USE_MESH_ROAMING && defined WLAN_USE_MESH_ROAMING_ACTIVATE_CLIENT_TRIGGERED_QUERIES)
void wifiRoamingQuery(void);
#endif

View File

@@ -11,5 +11,5 @@ dependencies:
type: idf
version: 5.3.1
manifest_hash: f88c9e5c2d75a9d5d6968fc67a90ef0cd7146dd6a3905a79c4dfcfc3b4fe6731
target: esp32s3
target: esp32
version: 1.0.0

View File

@@ -79,8 +79,6 @@
//ClassFlowControll + Main + SoftAP
#define WLAN_CONFIG_FILE "/sdcard/wlan.ini"
#define LAN_CONFIG_FILE "/sdcard/lan.ini"
//main
#define __SD_USE_ONE_LINE_MODE__
@@ -95,8 +93,8 @@
#define LOGFILE_LAST_PART_BYTES 80 * 1024 // 80 kBytes // Size of partial log file to return
#define SERVER_FILER_SCRATCH_BUFSIZE 1024
#define SERVER_HELPER_SCRATCH_BUFSIZE 1024
#define SERVER_FILER_SCRATCH_BUFSIZE 4096
#define SERVER_HELPER_SCRATCH_BUFSIZE 4096
#define SERVER_OTA_SCRATCH_BUFSIZE 1024
@@ -173,7 +171,7 @@
//#define WLAN_USE_MESH_ROAMING_ACTIVATE_CLIENT_TRIGGERED_QUERIES // Client can send query to AP requesting to roam (if RSSI lower than RSSI threshold)
/* WIFI roaming only client triggered by scanning the channels after each round (only if RSSI < RSSIThreshold) and trigger a disconnect to switch AP */
// #define WLAN_USE_ROAMING_BY_SCANNING
#define WLAN_USE_ROAMING_BY_SCANNING
//ClassFlowCNNGeneral
@@ -310,63 +308,6 @@
#define FLASH_GPIO GPIO_NUM_4 // PIN for flashlight LED
#define USE_PWM_LEDFLASH // if __LEDGLOBAL is defined, a global variable is used for LED control, otherwise locally and each time a new
#elif defined(BOARD_ESP32_S3_ALEKSEI) // Sonderversion für Aleksei mit ESP32s3 und Ethernet (PoE)
// HIGH=ENABLE
// ETH_EN activates power for the Ethernet
// PER_EN activates power for camera,leds,and SDcard, Battery measurement voltage divider
#define ETH_ENABLE GPIO_NUM_45
#define PER_ENABLE GPIO_NUM_46
// Ethernet (operated with SPI peripheral)
#define W5500_SPI_HOST SPI2_HOST
#define ETH_MOSI GPIO_NUM_1
#define ETH_MISO GPIO_NUM_14
#define ETH_CLK GPIO_NUM_21
#define ETH_CS GPIO_NUM_39
#define ETH_INT GPIO_NUM_38
// SD card (operated with SDMMC peripheral)
//-------------------------------------------------
#define GPIO_SDCARD_CLK GPIO_NUM_40
#define GPIO_SDCARD_CMD GPIO_NUM_42
#define GPIO_SDCARD_D0 GPIO_NUM_41
#ifndef __SD_USE_ONE_LINE_MODE__
#define GPIO_SDCARD_D1 GPIO_NUM_4
#define GPIO_SDCARD_D2 GPIO_NUM_12
#define GPIO_SDCARD_D3 GPIO_NUM_13
#else
#define GPIO_SDCARD_D1 GPIO_NUM_NC
#define GPIO_SDCARD_D2 GPIO_NUM_NC
#define GPIO_SDCARD_D3 GPIO_NUM_13
#endif
#define CAM_PIN_PWDN GPIO_NUM_NC
#define CAM_PIN_RESET GPIO_NUM_NC //software reset will be performed
#define CAM_PIN_XCLK GPIO_NUM_15
#define CAM_PIN_SIOD GPIO_NUM_4
#define CAM_PIN_SIOC GPIO_NUM_5
#define CAM_PIN_D7 GPIO_NUM_16
#define CAM_PIN_D6 GPIO_NUM_17
#define CAM_PIN_D5 GPIO_NUM_18
#define CAM_PIN_D4 GPIO_NUM_47
#define CAM_PIN_D3 GPIO_NUM_10
#define CAM_PIN_D2 GPIO_NUM_8
#define CAM_PIN_D1 GPIO_NUM_9
#define CAM_PIN_D0 GPIO_NUM_11
#define CAM_PIN_VSYNC GPIO_NUM_6
#define CAM_PIN_HREF GPIO_NUM_7
#define CAM_PIN_PCLK GPIO_NUM_13
//Statusled + ClassControllCamera
#define BLINK_GPIO GPIO_NUM_48 // PIN for red board LED
//ClassControllCamera
#define FLASH_GPIO GPIO_NUM_48 // PIN for flashlight LED
#define USE_PWM_LEDFLASH // if __LEDGLOBAL is defined, a global variable is used for LED control, otherwise locally and each time a new
#else
#error "Board not selected"
#endif //Board PIN Map

View File

@@ -25,9 +25,6 @@
#include "connect_wlan.h"
#include "read_wlanini.h"
#include "connect_lan.h"
#include "read_lanini.h"
#include "server_main.h"
#include "MainFlowControl.h"
#include "server_file.h"
@@ -216,28 +213,13 @@ bool Init_NVS_SDCard()
extern "C" void app_main(void)
{
TickType_t xDelay;
#if defined (BOARD_ESP32_S3_ALEKSEI)
// gpio_pad_select_gpio(ETH_EN);
// gpio_set_direction(ETH_EN, GPIO_MODE_OUTPUT);
// gpio_set_level(ETH_EN, 0);
// PER_ENABLE activates power for camera,leds,and SDcard, Battery measurement voltage divider
gpio_pad_select_gpio(PER_ENABLE);
gpio_set_direction(PER_ENABLE, GPIO_MODE_OUTPUT);
gpio_set_level(PER_ENABLE, 1);
xDelay = 1000 / portTICK_PERIOD_MS;
ESP_LOGI(TAG, "BOARD_ESP32_S3_ALEKSEI - Switch on Power for camera, ... : sleep for: %ldms", (long) xDelay * CONFIG_FREERTOS_HZ/portTICK_PERIOD_MS);
vTaskDelay( xDelay );
#endif //ETH_EN &&
//#ifdef CONFIG_HEAP_TRACING_STANDALONE
#if defined HEAP_TRACING_MAIN_WIFI || defined HEAP_TRACING_MAIN_START
//register a buffer to record the memory trace
ESP_ERROR_CHECK( heap_trace_init_standalone(trace_record, NUM_RECORDS) );
#endif
TickType_t xDelay;
#ifdef DISABLE_BROWNOUT_DETECTOR
WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0); //disable brownout detector
@@ -466,52 +448,26 @@ extern "C" void app_main(void)
ESP_ERROR_CHECK( heap_trace_start(HEAP_TRACE_LEAKS) );
#endif
bool lanEnabled = false;
#if defined(BOARD_ESP32_S3_ALEKSEI)
int iLanStatus = LoadLanFromFile(LAN_CONFIG_FILE);
if (iLanStatus == 0) {
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "LAN config loaded, init Lan...");
if (lan_init() != ESP_OK) {
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "LAN init failed. Device init aborted!");
// Read WLAN parameter and start WIFI
// ********************************************
int iWLANStatus = LoadWlanFromFile(WLAN_CONFIG_FILE);
if (iWLANStatus == 0) {
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "WLAN config loaded, init WIFI...");
if (wifi_init_sta() != ESP_OK) {
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "WIFI init failed. Device init aborted!");
StatusLED(WLAN_INIT, 3, true);
return;
}
else {
lanEnabled = true;
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "LAN init completed successfully");
}
}
else if(iLanStatus == -1) { // lan.ini not available, potentially empty or content not readable
LogFile.WriteToFile(ESP_LOG_WARN, TAG, "lan.ini not found, proceeding to wlan.ini");
}
else {
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Lan init failed. Unknown error!");
return; // No way to continue without reading the lan.ini
}
#endif
if(!lanEnabled){
// Read WLAN parameter and start WIFI
// ********************************************
int iWLANStatus = LoadWlanFromFile(WLAN_CONFIG_FILE);
if (iWLANStatus == 0) {
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "WLAN config loaded, init WIFI...");
if (wifi_init_sta() != ESP_OK) {
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "WIFI init failed. Device init aborted!");
StatusLED(WLAN_INIT, 3, true);
return;
}
init_basic_auth();
}
else if (iWLANStatus == -1) { // wlan.ini not available, potentially empty or content not readable
StatusLED(WLAN_INIT, 1, true);
return; // No way to continue without reading the wlan.ini
}
else if (iWLANStatus == -2) { // SSID or password not configured
StatusLED(WLAN_INIT, 2, true);
return; // No way to continue with empty SSID or password!
}
init_basic_auth();
}
else if (iWLANStatus == -1) { // wlan.ini not available, potentially empty or content not readable
StatusLED(WLAN_INIT, 1, true);
return; // No way to continue without reading the wlan.ini
}
else if (iWLANStatus == -2) { // SSID or password not configured
StatusLED(WLAN_INIT, 2, true);
return; // No way to continue with empty SSID or password!
}
xDelay = 2000 / portTICK_PERIOD_MS;
@@ -524,6 +480,7 @@ extern "C" void app_main(void)
{
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "Manual Time Sync failed during startup" );
}
// Set log level for wifi component to WARN level (default: INFO; only relevant for serial console)
// ********************************************
esp_log_level_set("wifi", ESP_LOG_WARN);

View File

@@ -41,7 +41,6 @@
bool isConfigINI = false;
bool isWlanINI = false;
bool isLanINI = false;
static const char *TAG = "WIFI AP";
@@ -100,13 +99,12 @@ void wifi_init_softAP(void)
void SendHTTPResponse(httpd_req_t *req)
{
std::string message = "<h1>AI-on-the-edge - BASIC SETUP</h1><p>This is an access point with a minimal server to setup the minimum required files and information on the device and the SD-card. ";
message += "This mode is always started if neither /wlan.ini nor /lan.ini is preset or the /config/config.ini. is missing<p>";
message += "The setup is done in 3 steps: 1. upload full inital configuration (sd-card content), 2. store WLAN/LAN access information, 3. reboot (and connect to WLANs/LANs)<p><p>";
message += "This mode is always started if one of the following files is missing: /wlan.ini or the /config/config.ini.<p>";
message += "The setup is done in 3 steps: 1. upload full inital configuration (sd-card content), 2. store WLAN access information, 3. reboot (and connect to WLANs)<p><p>";
message += "Please follow the below instructions.<p>";
httpd_resp_send_chunk(req, message.c_str(), strlen(message.c_str()));
isWlanINI = FileExists(WLAN_CONFIG_FILE);
isLanINI = FileExists(LAN_CONFIG_FILE);
if (!isConfigINI)
{
@@ -131,53 +129,33 @@ void SendHTTPResponse(httpd_req_t *req)
httpd_resp_send_chunk(req, message.c_str(), strlen(message.c_str()));
return;
}
if (!isWlanINI && !isLanINI)
if (!isWlanINI)
{
message = "<h3>2. WLAN access credentials</h3><p>";
message += "Interface: <select id=\"iface\" onchange=\"toggle()\">";
message += "<option value=\"wifi\" selected>Wi-Fi</option>";
message += "<option value=\"eth\">Ethernet</option></select><p>";
/* Wi-Fi-only fields wrapped in a <div id="wifi"> for easy hide/show */
message += "<div id=\"wifi\">";
message = "<h3>2. WLAN access credentials</h3><p>";
message += "<table>";
message += "<tr><td>WLAN-SSID</td><td><input id=\"ssid\"></td><td>SSID of the WLAN</td></tr>";
message += "<tr><td>WLAN-Password</td><td><input id=\"password\"></td><td><b>ATTENTION:</b> sent unencrypted</td></tr>";
message += "</table></div><p>";
message += "<h4>ATTENTION:</h4>Be sure about the WLAN/LAN settings. They cannot be reset afterwards. "
"If SSID or password are wrong you must edit <i>wlan.ini</i> on the SD-card!<p>";
httpd_resp_send_chunk(req, message.c_str(), message.length());
/* ---- Button + JS ---------------------------------------------------- */
message.clear();
message = "<button class=\"button\" id=\"saveBtn\" onclick=\"wr()\">Write wlan.ini</button>";
message += R"JS(
<script>
function toggle(){
const wifiSelected = (iface.value === 'wifi');
wifi.style.display = wifiSelected ? 'block' : 'none';
/* change button label */
saveBtn.textContent = wifiSelected ? 'Write wlan.ini' : 'Write lan.ini';
}
async function wr(){
let url = '/config?type=' + iface.value;
if(iface.value==='wifi'){
url += '&ssid=' + encodeURIComponent(ssid.value) +
'&pwd=' + encodeURIComponent(password.value);
}
await fetch(url);
await new Promise(r=>setTimeout(r,500));
location.reload();
}
</script>)JS";
httpd_resp_send_chunk(req, message.c_str(), message.length());
/* finish response */
httpd_resp_send_chunk(req, nullptr, 0);
return; // done
}
message += "<tr><td>WLAN-SSID</td><td><input type=\"text\" name=\"ssid\" id=\"ssid\"></td><td>SSID of the WLAN</td></tr>";
message += "<tr><td>WLAN-Password</td><td><input type=\"text\" name=\"password\" id=\"password\"></td><td>ATTENTION: the password will not be encrypted during the sending.</td><tr>";
message += "</table><p>";
message += "<h4>ATTENTION:<h4>Be sure about the WLAN settings. They cannot be reset afterwards. If ssid or password is wrong, you need to take out the sd-card and manually change them in \"wlan.ini\"!<p>";
httpd_resp_send_chunk(req, message.c_str(), strlen(message.c_str()));
// message = "</tr><tr><td> Hostname</td><td><input type=\"text\" name=\"hostname\" id=\"hostname\"></td><td></td>";
// message += "</tr><tr><td>Fixed IP</td><td><input type=\"text\" name=\"ip\" id=\"ip\"></td><td>Leave emtpy if set by router (DHCP)</td></tr>";
// message += "<tr><td>Gateway</td><td><input type=\"text\" name=\"gateway\" id=\"gateway\"></td><td>Leave emtpy if set by router (DHCP)</td></tr>";
// message += "<tr><td>Netmask</td><td><input type=\"text\" name=\"netmask\" id=\"netmask\"></td><td>Leave emtpy if set by router (DHCP)</td>";
// message += "</tr><tr><td>DNS</td><td><input type=\"text\" name=\"dns\" id=\"dns\"></td><td>Leave emtpy if set by router (DHCP)</td></tr>";
// message += "<tr><td>RSSI Threshold</td><td><input type=\"number\" name=\"name\" id=\"threshold\" min=\"-100\" max=\"0\" step=\"1\" value = \"0\"></td><td>WLAN Mesh Parameter: Threshold for RSSI value to check for start switching access point in a mesh system (if actual RSSI is lower). Possible values: -100 to 0, 0 = disabled - Value will be transfered to wlan.ini at next startup)</td></tr>";
// httpd_resp_send_chunk(req, message.c_str(), strlen(message.c_str()));
message = "<button class=\"button\" type=\"button\" onclick=\"wr()\">Write wlan.ini</button>";
message += "<script language=\"JavaScript\">async function wr(){";
message += "api = \"/config?\"+\"ssid=\"+document.getElementById(\"ssid\").value+\"&pwd=\"+document.getElementById(\"password\").value;";
// message += "api = \"/config?\"+\"ssid=\"+document.getElementById(\"ssid\").value+\"&pwd=\"+document.getElementById(\"password\").value+\"&hn=\"+document.getElementById(\"hostname\").value+\"&ip=\"+document.getElementById(\"ip\").value+\"&gw=\"+document.getElementById(\"gateway\").value+\"&nm=\"+document.getElementById(\"netmask\").value+\"&dns=\"+document.getElementById(\"dns\").value+\"&rssithreshold=\"+document.getElementById(\"threshold\").value;";
message += "fetch(api);await new Promise(resolve => setTimeout(resolve, 1000));location.reload();}</script>";
httpd_resp_send_chunk(req, message.c_str(), strlen(message.c_str()));
return;
}
message = "<h3>3. Reboot</h3><p>";
message += "After triggering the reboot, the zip-files gets extracted and written to the sd-card.<br>The ESP32 will restart two times and then connect to your access point. Please find the IP in your router settings and access it with the new ip-address.<p>";
@@ -229,8 +207,6 @@ esp_err_t config_ini_handler(httpd_req_t *req)
std::string dns = "";
std::string rssithreshold = ""; //rssi threshold for WIFI roaming
std::string text = "";
std::string type = "";
if (httpd_req_get_url_query_str(req, _query, 400) == ESP_OK)
@@ -290,49 +266,27 @@ esp_err_t config_ini_handler(httpd_req_t *req)
ESP_LOGD(TAG, "rssithreshold is found: %s", _valuechar);
rssithreshold = UrlDecode(std::string(_valuechar));
}
if (httpd_query_key_value(_query, "type", _valuechar, 100) == ESP_OK)
{
ESP_LOGD(TAG, "type is found: %s", _valuechar);
type = UrlDecode(std::string(_valuechar));
}
}
FILE* configfilehandle = nullptr;
if(type == "wifi"){
configfilehandle = fopen(WLAN_CONFIG_FILE, "w");
FILE* configfilehandle = fopen(WLAN_CONFIG_FILE, "w");
text = ";++++++++++++++++++++++++++++++++++\n";
text += "; AI on the edge - WLAN configuration\n";
text += "; ssid: Name of WLAN network (mandatory), e.g. \"WLAN-SSID\"\n";
text += "; password: Password of WLAN network (mandatory), e.g. \"PASSWORD\"\n\n";
fputs(text.c_str(), configfilehandle);
if (ssid.length())
ssid = "ssid = \"" + ssid + "\"\n";
else
ssid = "ssid = \"\"\n";
fputs(ssid.c_str(), configfilehandle);
if (pwd.length())
pwd = "password = \"" + pwd + "\"\n";
else
pwd = "password = \"\"\n";
fputs(pwd.c_str(), configfilehandle);
}
else{
configfilehandle = fopen(LAN_CONFIG_FILE, "w");
text = ";++++++++++++++++++++++++++++++++++\n";
text += "; AI on the edge - WLAN configuration\n";
text += "; ssid: Name of WLAN network (mandatory), e.g. \"WLAN-SSID\"\n";
text += "; password: Password of WLAN network (mandatory), e.g. \"PASSWORD\"\n\n";
fputs(text.c_str(), configfilehandle);
text = ";++++++++++++++++++++++++++++++++++\n";
text += "; AI on the edge - WLAN configuration\n";
text += "; ssid: Name of WLAN network (mandatory), e.g. \"WLAN-SSID\"\n";
text += "; password: Password of WLAN network (mandatory), e.g. \"PASSWORD\"\n\n";
fputs(text.c_str(), configfilehandle);
if (ssid.length())
ssid = "ssid = \"" + ssid + "\"\n";
else
ssid = "ssid = \"\"\n";
fputs(ssid.c_str(), configfilehandle);
fputs(ssid.c_str(), configfilehandle);
if (pwd.length())
pwd = "password = \"" + pwd + "\"\n";
else
pwd = "password = \"\"\n";
fputs(pwd.c_str(), configfilehandle);
}
fputs(pwd.c_str(), configfilehandle);
text = "\n;++++++++++++++++++++++++++++++++++\n";
text += "; Hostname: Name of device in network\n";
@@ -379,24 +333,22 @@ esp_err_t config_ini_handler(httpd_req_t *req)
dns = ";dns = \"xxx.xxx.xxx.xxx\"\n";
fputs(dns.c_str(), configfilehandle);
if(type == "wifi"){
text = "\n;++++++++++++++++++++++++++++++++++\n";
text += "; WIFI Roaming:\n";
text += "; Network assisted roaming protocol is activated by default\n";
text += "; AP / mesh system needs to support roaming protocol 802.11k/v\n";
text += ";\n";
text += "; Optional feature (usually not neccessary):\n";
text += "; RSSI Threshold for client requested roaming query (RSSI < RSSIThreshold)\n";
text += "; Note: This parameter can be configured via WebUI configuration\n";
text += "; Default: 0 = Disable client requested roaming query\n\n";
fputs(text.c_str(), configfilehandle);
text = "\n;++++++++++++++++++++++++++++++++++\n";
text += "; WIFI Roaming:\n";
text += "; Network assisted roaming protocol is activated by default\n";
text += "; AP / mesh system needs to support roaming protocol 802.11k/v\n";
text += ";\n";
text += "; Optional feature (usually not neccessary):\n";
text += "; RSSI Threshold for client requested roaming query (RSSI < RSSIThreshold)\n";
text += "; Note: This parameter can be configured via WebUI configuration\n";
text += "; Default: 0 = Disable client requested roaming query\n\n";
fputs(text.c_str(), configfilehandle);
if (rssithreshold.length())
rssithreshold = "RSSIThreshold = " + rssithreshold + "\n";
else
rssithreshold = "RSSIThreshold = 0\n";
fputs(rssithreshold.c_str(), configfilehandle);
}
if (rssithreshold.length())
rssithreshold = "RSSIThreshold = " + rssithreshold + "\n";
else
rssithreshold = "RSSIThreshold = 0\n";
fputs(rssithreshold.c_str(), configfilehandle);
fflush(configfilehandle);
fclose(configfilehandle);
@@ -555,15 +507,14 @@ void CheckStartAPMode()
{
isConfigINI = FileExists(CONFIG_FILE);
isWlanINI = FileExists(WLAN_CONFIG_FILE);
isLanINI = FileExists(LAN_CONFIG_FILE);
if (!isConfigINI)
ESP_LOGW(TAG, "config.ini not found!");
if (!isWlanINI && !isLanINI)
ESP_LOGW(TAG, "wlan.ini and lan.ini not found!");
if (!isWlanINI)
ESP_LOGW(TAG, "wlan.ini not found!");
if (!isConfigINI || (!isWlanINI && !isLanINI))
if (!isConfigINI || !isWlanINI)
{
ESP_LOGI(TAG, "Starting access point for remote configuration");
StatusLED(AP_OR_OTA, 2, true);

View File

@@ -10,7 +10,7 @@
[platformio]
src_dir = main
default_envs = esp32s3-aleksei
default_envs = esp32cam
[common:idf]
build_flags =
@@ -72,31 +72,6 @@ build_flags =
board_build.partitions = partitions.csv
monitor_speed = 115200
; The main env - default
[env:esp32s3-aleksei]
extends = common:esp32-idf
board = seeed_xiao_esp32s3
framework = espidf
build_flags =
; ### common imported :
${common:esp32-idf.build_flags}
${flags:runtime.build_flags}
; ### Sofware options : (can be set in defines.h)
-D BOARD_ESP32_S3_ALEKSEI
-D ENABLE_MQTT
;-D MQTT_PROTOCOL_311
-D MQTT_ENABLE_SSL
;-D MQTT_ENABLE_WS
;-D MQTT_ENABLE_WSS
-D MQTT_SUPPORTED_FEATURE_SKIP_CRT_CMN_NAME_CHECK
;-D MQTT_SUPPORTED_FEATURE_CRT_CMN_NAME
;-D MQTT_SUPPORTED_FEATURE_CLIENT_KEY_PASSWORD
-D ENABLE_INFLUXDB
-D ENABLE_WEBHOOK
-D ENABLE_SOFTAP
board_build.partitions = partitions.csv
monitor_speed = 115200
; full standalone dev mode
; As sample, the board is nod32s instead of esp32cam (do not change nothing in fact :)

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

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").
!!! 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.
!!! 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,11 +10,11 @@ Alternatively you can set the parameter `DecimalShift` to `3` so the value is co
List of supported options:
- `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_gal` (uses `gal/h` as rate, not officially supported by Homeassistant!)
- `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)
- `energy_wh` (uses `W` as rate)
- `energy_kwh` (uses `KW` as rate)

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.
!!! 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!
!!! 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`.
!!! 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

@@ -1,7 +1,7 @@
# Parameter `ChangeRateThreshold`
Default Value: `2`
Range: `1` .. `9`.
Range: `0` .. `9`.
Threshold parameter for change rate detection.<br>
This parameter is intended to compensate for small reading fluctuations that occur when the meter does not change its value for a long time (e.g. at night) or slightly turns backwards. This can eg. happen on watermeters.
@@ -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.
!!! 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
- Smallest ROI provides value for `0.000'x` (Eg. a water meter with 4 pointers behind the decimal point)
- ChangeRateThreshold = 2
#### With `Extended Resolution` **disabled**
#### With `ExtendedResolution` **disabled**
PreValue: `123.456'7` -> Threshold = `+/-0.000'2`.<br>
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>
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.
!!! 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`.
!!! 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.
!!! 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.
!!! 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).
!!! 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`!
!!! 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.

View File

@@ -1,145 +1,145 @@
[TakeImage]
;RawImagesLocation = /log/source
;RawImagesRetention = 15
WaitBeforeTakingPicture = 2
CamGainceiling = x8
CamQuality = 10
CamBrightness = 0
CamContrast = 0
CamSaturation = 0
CamSharpness = 0
CamAutoSharpness = false
CamSpecialEffect = no_effect
CamWbMode = auto
CamAwb = true
CamAwbGain = true
CamAec = true
CamAec2 = true
CamAeLevel = 2
CamAecValue = 600
CamAgc = true
CamAgcGain = 8
CamBpc = true
CamWpc = true
CamRawGma = true
CamLenc = true
CamHmirror = false
CamVflip = false
CamDcw = true
CamDenoise = 0
CamZoom = false
CamZoomOffsetX = 0
CamZoomOffsetY = 0
CamZoomSize = 0
LEDIntensity = 50
Demo = false
[Alignment]
InitialRotate = 0.0
SearchFieldX = 20
SearchFieldY = 20
AlignmentAlgo = default
/config/ref0.jpg 103 271
/config/ref1.jpg 442 142
[Digits]
Model = /config/dig-cont_0712_s3_q.tflite
CNNGoodThreshold = 0.5
;ROIImagesLocation = /log/digit
;ROIImagesRetention = 3
main.dig1 294 126 30 54 false
main.dig2 343 126 30 54 false
main.dig3 391 126 30 54 false
[Analog]
Model = /config/ana-cont_1300_s2.tflite
CNNGoodThreshold = 0.5
;ROIImagesLocation = /log/analog
;ROIImagesRetention = 3
main.ana1 432 230 92 92 false
main.ana2 379 332 92 92 false
main.ana3 283 374 92 92 false
main.ana4 155 328 92 92 false
[PostProcessing]
main.DecimalShift = 0
main.AnalogDigitTransitionStart = 9.2
main.ChangeRateThreshold = 2
PreValueUse = true
PreValueAgeStartup = 720
main.AllowNegativeRates = false
main.MaxRateValue = 0.05
;main.MaxRateType = AbsoluteChange
main.ExtendedResolution = false
main.IgnoreLeadingNaN = false
ErrorMessage = true
main.CheckDigitIncreaseConsistency = false
;[MQTT]
;Uri = mqtt://IP-ADRESS:1883
;MainTopic = watermeter
;ClientID = watermeter
;user = USERNAME
;password = PASSWORD
RetainMessages = false
HomeassistantDiscovery = false
;MeterType = other
;CACert = /config/certs/RootCA.pem
;ClientCert = /config/certs/client.pem.crt
;ClientKey = /config/certs/client.pem.key
;ValidateServerCert = true
;DomoticzTopicIn = domoticz/in
;main.DomoticzIDX = 0
;[InfluxDB]
;Uri = undefined
;Database = undefined
;user = undefined
;password = undefined
;main.Measurement = undefined
;main.Field = undefined
;[InfluxDBv2]
;Uri = undefined
;Bucket = undefined
;Org = undefined
;Token = undefined
;main.Measurement = undefined
;main.Field = undefined
;[Webhook]
;Uri = undefined
;ApiKey = undefined
;UploadImg = 0
[GPIO]
;IO0 = input disabled 10 false false
;IO1 = input disabled 10 false false
;IO3 = input disabled 10 false false
;IO4 = built-in-led disabled 10 false false
IO12 = external-flash-ws281x disabled 10 false false
;IO13 = input-pullup disabled 10 false false
LEDType = WS2812
LEDNumbers = 4
LEDColor = 200 200 200
[AutoTimer]
Interval = 5
SleepWhileIdle = false
[DataLogging]
DataLogActive = true
DataFilesRetention = 3
[Debug]
LogLevel = 1
LogfilesRetention = 3
[System]
TimeZone = CET-1CEST,M3.5.0,M10.5.0/3
;TimeServer = pool.ntp.org
;Hostname = undefined
RSSIThreshold = -75
CPUFrequency = 160
Tooltip = true
SetupMode = true
[TakeImage]
;RawImagesLocation = /log/source
;RawImagesRetention = 15
WaitBeforeTakingPicture = 2
CamGainceiling = x8
CamQuality = 10
CamBrightness = 0
CamContrast = 0
CamSaturation = 0
CamSharpness = 0
CamAutoSharpness = false
CamSpecialEffect = no_effect
CamWbMode = auto
CamAwb = true
CamAwbGain = true
CamAec = true
CamAec2 = true
CamAeLevel = 2
CamAecValue = 600
CamAgc = true
CamAgcGain = 8
CamBpc = true
CamWpc = true
CamRawGma = true
CamLenc = true
CamHmirror = false
CamVflip = false
CamDcw = true
CamDenoise = 0
CamZoom = false
CamZoomOffsetX = 0
CamZoomOffsetY = 0
CamZoomSize = 0
LEDIntensity = 50
Demo = false
[Alignment]
InitialRotate = 0.0
SearchFieldX = 20
SearchFieldY = 20
AlignmentAlgo = default
/config/ref0.jpg 103 271
/config/ref1.jpg 442 142
[Digits]
Model = /config/dig-cont_0900_s3_q.tflite
CNNGoodThreshold = 0.5
;ROIImagesLocation = /log/digit
;ROIImagesRetention = 3
main.dig1 294 126 30 54 false
main.dig2 343 126 30 54 false
main.dig3 391 126 30 54 false
[Analog]
Model = /config/ana-cont_1500_s2_q.tflite
CNNGoodThreshold = 0.5
;ROIImagesLocation = /log/analog
;ROIImagesRetention = 3
main.ana1 432 230 92 92 false
main.ana2 379 332 92 92 false
main.ana3 283 374 92 92 false
main.ana4 155 328 92 92 false
[PostProcessing]
main.DecimalShift = 0
main.AnalogDigitTransitionStart = 9.2
main.ChangeRateThreshold = 2
PreValueUse = true
PreValueAgeStartup = 720
main.AllowNegativeRates = false
main.MaxRateValue = 0.05
;main.MaxRateType = AbsoluteChange
main.ExtendedResolution = false
main.IgnoreLeadingNaN = false
ErrorMessage = true
main.CheckDigitIncreaseConsistency = false
;[MQTT]
;Uri = mqtt://IP-ADRESS:1883
;MainTopic = watermeter
;ClientID = watermeter
;user = USERNAME
;password = PASSWORD
RetainMessages = false
HomeassistantDiscovery = false
;MeterType = other
;CACert = /config/certs/RootCA.pem
;ClientCert = /config/certs/client.pem.crt
;ClientKey = /config/certs/client.pem.key
;ValidateServerCert = true
;DomoticzTopicIn = domoticz/in
;main.DomoticzIDX = 0
;[InfluxDB]
;Uri = undefined
;Database = undefined
;user = undefined
;password = undefined
;main.Measurement = undefined
;main.Field = undefined
;[InfluxDBv2]
;Uri = undefined
;Bucket = undefined
;Org = undefined
;Token = undefined
;main.Measurement = undefined
;main.Field = undefined
;[Webhook]
;Uri = undefined
;ApiKey = undefined
;UploadImg = 0
;[GPIO]
;MainTopicMQTT = wasserzaehler/GPIO
;IO0 = input disabled 10 false false
;IO1 = input disabled 10 false false
;IO3 = input disabled 10 false false
;IO4 = built-in-led disabled 10 false false
;IO12 = input-pullup disabled 10 false false
;IO13 = input-pullup disabled 10 false false
LEDType = WS2812
LEDNumbers = 2
LEDColor = 150 150 150
[AutoTimer]
Interval = 5
[DataLogging]
DataLogActive = true
DataFilesRetention = 3
[Debug]
LogLevel = 1
LogfilesRetention = 3
[System]
TimeZone = CET-1CEST,M3.5.0,M10.5.0/3
;TimeServer = pool.ntp.org
;Hostname = undefined
RSSIThreshold = -75
CPUFrequency = 160
Tooltip = true
SetupMode = true

Binary file not shown.

Binary file not shown.

View File

@@ -969,7 +969,7 @@
</td>
<td>
<input required type="number" id="PostProcessing_ChangeRateThreshold_value1" step="1" min="0" max="9" value="2"
oninput="(!validity.rangeUnderflow||(value=1)) && (!validity.rangeOverflow||(value=9)) &&
oninput="(!validity.rangeUnderflow||(value=0)) && (!validity.rangeOverflow||(value=9)) &&
(!validity.stepMismatch||(value=parseInt(this.value)));">
</td>
<td>$TOOLTIP_PostProcessing_NUMBER.ChangeRateThreshold</td>
@@ -1744,14 +1744,14 @@
</tr>
<!------------- GPIO4 end ------------------>
<!------------- GPIO47 begin ------------------>
<!------------- GPIO12 begin ------------------>
<tr class="GPIO_item">
<td class="indent1">
<input type="checkbox" id="GPIO_IO47_enabled" value="1" onclick = 'InvertEnableItem("GPIO", "IO47")' unchecked>
<label for=GPIO_IO47_enabled><span id="GPIO_IO47_text">GPIO47 Configuration</span></label>
<input type="checkbox" id="GPIO_IO12_enabled" value="1" onclick = 'InvertEnableItem("GPIO", "IO12")' unchecked>
<label for=GPIO_IO12_enabled><span id="GPIO_IO12_text">GPIO12 Configuration</span></label>
</td>
<td>
<select id="GPIO_IO47_value1">
<select id="GPIO_IO12_value1">
<option value="input">input</option>
<option value="input-pullup">input pullup</option>
<option value="input-pulldown">input pulldown</option>
@@ -1761,15 +1761,15 @@
<option value="external-flash-ws281x">external flash light ws281x controlled</option>
</select>
</td>
<td>$TOOLTIP_GPIO_IO47</td>
<td>$TOOLTIP_GPIO_IO12</td>
</tr>
<tr class="GPIO_IO47 GPIO_item expert">
<tr class="GPIO_IO12 GPIO_item expert">
<td class="indent2">
<span class="GPIO_IO47 GPIO_item">GPIO47 Use Interrupt</span>
<span class="GPIO_IO12 GPIO_item">GPIO12 Use Interrupt</span>
</td>
<td>
<select class="GPIO_IO47 GPIO_item" id="GPIO_IO47_value2">
<select class="GPIO_IO12 GPIO_item" id="GPIO_IO12_value2">
<option value="disabled">disabled</option>
<option value="rising-edge">rising edge</option>
<option value="falling-edge">falling edge</option>
@@ -1781,45 +1781,45 @@
<td></td>
</tr>
<tr class="GPIO_IO47 GPIO_item expert">
<tr class="GPIO_IO12 GPIO_item expert">
<td class="indent2">
<span class="GPIO_IO47 GPIO_item">GPIO47 PWM Duty Cycle Resolution</span>
<span class="GPIO_IO12 GPIO_item">GPIO12 PWM Duty Cycle Resolution</span>
</td>
<td>
<input required type="number" id="GPIO_IO47_value3" min="1" max="20"
<input required type="number" id="GPIO_IO12_value3" min="1" max="20"
oninput="(!validity.rangeUnderflow||(value=1)) && (!validity.rangeOverflow||(value=20)) &&
(!validity.stepMismatch||(value=parseInt(this.value)));"><span class="GPIO_IO47 GPIO_item">Bits</span>
(!validity.stepMismatch||(value=parseInt(this.value)));"><span class="GPIO_IO12 GPIO_item">Bits</span>
</td>
<td></td>
</tr>
<tr class="GPIO_IO47 GPIO_item expert">
<tr class="GPIO_IO12 GPIO_item expert">
<td class="indent2">
<span class="GPIO_IO47 GPIO_item">GPIO47 Enable MQTT</span>
<span class="GPIO_IO12 GPIO_item">GPIO12 Enable MQTT</span>
</td>
<td><input type="checkbox" id="GPIO_IO47_value4"></td>
<td><input type="checkbox" id="GPIO_IO12_value4"></td>
<td></td>
</tr>
<tr class="GPIO_IO47 GPIO_item expert">
<tr class="GPIO_IO12 GPIO_item expert">
<td class="indent2">
<span class="GPIO_IO47 GPIO_item">GPIO47 Enable REST API</span>
<span class="GPIO_IO12 GPIO_item">GPIO12 Enable REST API</span>
</td>
<td><input type="checkbox" id="GPIO_IO47_value5"></td>
<td><input type="checkbox" id="GPIO_IO12_value5"></td>
<td></td>
</tr>
<tr class="GPIO_IO47 GPIO_item expert">
<tr class="GPIO_IO12 GPIO_item expert">
<td class="indent2">
<span class="GPIO_IO47 GPIO_item">GPIO47 Name</span>
<span class="GPIO_IO12 GPIO_item">GPIO12 Name</span>
</td>
<td><input type="text" id="GPIO_IO47_value6"></td>
<td><input type="text" id="GPIO_IO12_value6"></td>
<td></td>
</tr>
<tr class="GPIO_item" unused_id="wstypeex3">
<td class="indent1">
<span class="GPIO_IO47 GPIO_item" id="GPIO_LEDType_text">LED Type (NeoPixel)</span>
<span class="GPIO_IO12 GPIO_item" id="GPIO_LEDType_text">LED Type (NeoPixel)</span>
</td>
<td class="GPIO_item">
<select class="GPIO_item" id="GPIO_LEDType_value1">
@@ -1848,7 +1848,7 @@
<span class="GPIO_item" id="GPIO_LEDColor_text">LED Color</span>
</td>
<td>
R <input required type="number" class="GPIO_IO47 GPIO_item" id="GPIO_LEDColor_value1"
R <input required type="number" class="GPIO_IO12 GPIO_item" id="GPIO_LEDColor_value1"
min="0" max="255" step="1" oninput="(!validity.rangeUnderflow||(value=0)) && (!validity.rangeOverflow||(value=255)) &&
(!validity.stepMismatch||(value=parseInt(this.value)));">
</td>
@@ -1858,7 +1858,7 @@
<tr class="GPIO_item" unused_id="LEDRGBex9">
<td></td>
<td>
G <input required type="number" class="GPIO_IO47 GPIO_item" id="GPIO_LEDColor_value2"
G <input required type="number" class="GPIO_IO12 GPIO_item" id="GPIO_LEDColor_value2"
min="0" max="255" step="1" oninput="(!validity.rangeUnderflow||(value=0)) && (!validity.rangeOverflow||(value=255)) &&
(!validity.stepMismatch||(value=parseInt(this.value)));">
</td>
@@ -1867,12 +1867,12 @@
<tr class="GPIO_item" unused_id="LEDRGBex9">
<td></td>
<td>
B <input required type="number" class="GPIO_IO47 GPIO_item" id="GPIO_LEDColor_value3"
B <input required type="number" class="GPIO_IO12 GPIO_item" id="GPIO_LEDColor_value3"
min="0" max="255" step="1" oninput="(!validity.rangeUnderflow||(value=0)) && (!validity.rangeOverflow||(value=255)) &&
(!validity.stepMismatch||(value=parseInt(this.value)));">
</td>
</tr>
<!------------- GPIO47 end ------------------>
<!------------- GPIO12 end ------------------>
<!------------- GPIO13 begin ------------------>
<tr class="GPIO_IO13 GPIO_item expert">
@@ -1974,19 +1974,6 @@
<td>$TOOLTIP_AutoTimer_Interval</td>
</tr>
<tr>
<td class="indent1">
<class id="AutoTimer_SleepWhileIdle_text" style="color:black;">Sleep While Idle</class>
</td>
<td>
<select id="AutoTimer_SleepWhileIdle_value1">
<option value="true">enabled (true)</option>
<option value="false" selected>disabled (false)</option>
</select>
</td>
<td>$TOOLTIP_AutoTimer_SleepWhileIdle</td>
</tr>
<!------------- Data Logging ------------------>
<tr style="border-bottom: 2px solid lightgray;">
<td colspan="3" style="padding-left: 0px; padding-bottom: 3px;"><h4>Data Logging</h4></td>
@@ -2407,7 +2394,7 @@ function UpdateInput() {
WriteParameter(param, category, "GPIO", "IO1", true);
WriteParameter(param, category, "GPIO", "IO3", true);
WriteParameter(param, category, "GPIO", "IO4", true);
WriteParameter(param, category, "GPIO", "IO47", true);
WriteParameter(param, category, "GPIO", "IO12", true);
WriteParameter(param, category, "GPIO", "IO13", true);
WriteParameter(param, category, "GPIO", "LEDType", false);
WriteParameter(param, category, "GPIO", "LEDNumbers", false);
@@ -2415,7 +2402,6 @@ function UpdateInput() {
//WriteParameter(param, category, "AutoTimer", "AutoStart", false);
WriteParameter(param, category, "AutoTimer", "Interval", false);
WriteParameter(param, category, "AutoTimer", "SleepWhileIdle", false);
WriteParameter(param, category, "DataLogging", "DataLogActive", false);
WriteParameter(param, category, "DataLogging", "DataFilesRetention", false);
@@ -2576,7 +2562,7 @@ function ReadParameterAll() {
ReadParameter(param, "GPIO", "IO1", true);
ReadParameter(param, "GPIO", "IO3", true);
ReadParameter(param, "GPIO", "IO4", true);
ReadParameter(param, "GPIO", "IO47", true);
ReadParameter(param, "GPIO", "IO12", true);
ReadParameter(param, "GPIO", "IO13", true);
ReadParameter(param, "GPIO", "LEDType", false);
ReadParameter(param, "GPIO", "LEDNumbers", false);
@@ -2592,7 +2578,6 @@ function ReadParameterAll() {
//ReadParameter(param, "AutoTimer", "AutoStart", false);
ReadParameter(param, "AutoTimer", "Interval", false);
ReadParameter(param, "AutoTimer", "SleepWhileIdle", false);
ReadParameter(param, "DataLogging", "DataLogActive", false);
ReadParameter(param, "DataLogging", "DataFilesRetention", false);
@@ -2656,7 +2641,7 @@ function UpdateExpertModus() {
}
});
Array.from(document.querySelector("#GPIO_IO47_value1").options).forEach(function(option_element) {
Array.from(document.querySelector("#GPIO_IO12_value1").options).forEach(function(option_element) {
if (option_element.value != "external-flash-ws281x") {
option_element.hidden = _hidden;
}

View File

@@ -247,7 +247,7 @@ function ParseConfig() {
ParamAddValue(param, catname, "IO1", 6, false, "", [null, null, /^[0-9]*$/, null, null, /^[a-zA-Z0-9_-]*$/]);
ParamAddValue(param, catname, "IO3", 6, false, "", [null, null, /^[0-9]*$/, null, null, /^[a-zA-Z0-9_-]*$/]);
ParamAddValue(param, catname, "IO4", 6, false, "", [null, null, /^[0-9]*$/, null, null, /^[a-zA-Z0-9_-]*$/]);
ParamAddValue(param, catname, "IO47", 6, false, "", [null, null, /^[0-9]*$/, null, null, /^[a-zA-Z0-9_-]*$/]);
ParamAddValue(param, catname, "IO12", 6, false, "", [null, null, /^[0-9]*$/, null, null, /^[a-zA-Z0-9_-]*$/]);
ParamAddValue(param, catname, "IO13", 6, false, "", [null, null, /^[0-9]*$/, null, null, /^[a-zA-Z0-9_-]*$/]);
ParamAddValue(param, catname, "LEDType");
ParamAddValue(param, catname, "LEDNumbers");