mirror of
https://github.com/jomjol/AI-on-the-edge-device.git
synced 2025-12-09 13:06:54 +03:00
Compare commits
15 Commits
v16.0.0
...
esp32s3-te
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
247f7ee8e2 | ||
|
|
149bbdc553 | ||
|
|
58c7bce8b5 | ||
|
|
64bf79b288 | ||
|
|
13e9fa2cc4 | ||
|
|
de48d0b008 | ||
|
|
61085d3861 | ||
|
|
8494f36069 | ||
|
|
3e67aeec0d | ||
|
|
e85e92762e | ||
|
|
eb9bf3c7c1 | ||
|
|
9c604c9cbc | ||
|
|
636a17117b | ||
|
|
8d4b28b481 | ||
|
|
9a82e0ac92 |
11
.github/workflows/build.yaml
vendored
11
.github/workflows/build.yaml
vendored
@@ -286,6 +286,7 @@ jobs:
|
||||
rm -rf ./sd-card/html
|
||||
rm -rf ./sd-card/demo
|
||||
cp -r ./html ./sd-card/ # Overwrite the Web UI with the preprocessed files
|
||||
rm -f ./sd-card/Readme.md
|
||||
cp -r ./demo ./sd-card/
|
||||
cd sd-card; rm -rf html/param-tooltips; zip -r ../manual_setup/sd-card.zip *; cd ..
|
||||
cd ./manual_setup
|
||||
@@ -434,13 +435,13 @@ jobs:
|
||||
- name: Add binary to Web Installer and update manifest
|
||||
run: |
|
||||
echo "Updating Web installer to use firmware from ${{ steps.last_release.outputs.tag_name }}..."
|
||||
rm -f docs/binary/firmware.bin
|
||||
rm -f webinstaller/binary/firmware.bin
|
||||
wget ${{ github.server_url }}/${{ github.repository }}/releases/download/${{ steps.last_release.outputs.tag_name }}/AI-on-the-edge-device__update__${{ steps.last_release.outputs.tag_name }}.zip
|
||||
unzip AI-on-the-edge-device__update__${{ steps.last_release.outputs.tag_name }}.zip
|
||||
cp -f firmware.bin docs/binary/firmware.bin
|
||||
cp -f firmware.bin webinstaller/binary/firmware.bin
|
||||
echo "Updating index and manifest file..."
|
||||
sed -i 's/$VERSION/${{ steps.last_release.outputs.tag_name }}/g' docs/index.html
|
||||
sed -i 's/$VERSION/${{ steps.last_release.outputs.tag_name }}/g' docs/manifest.json
|
||||
sed -i 's/$VERSION/${{ steps.last_release.outputs.tag_name }}/g' webinstaller/index.html
|
||||
sed -i 's/$VERSION/${{ steps.last_release.outputs.tag_name }}/g' webinstaller/manifest.json
|
||||
|
||||
- name: Setup Pages
|
||||
uses: actions/configure-pages@v4
|
||||
@@ -448,7 +449,7 @@ jobs:
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-pages-artifact@v2
|
||||
with:
|
||||
path: 'docs'
|
||||
path: 'webinstaller'
|
||||
|
||||
- name: Deploy to GitHub Pages
|
||||
id: deployment
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# This updates the Web Installer with the files from the docs folder and the binary of the latest release
|
||||
# This updates the Web Installer with the files from the webinstaller folder and the binary of the latest release
|
||||
# it only gets run on:
|
||||
# - Manually triggered
|
||||
# Make sure to also update the lower part of build.yml!
|
||||
@@ -11,7 +11,7 @@ on:
|
||||
# branches:
|
||||
# - rolling
|
||||
# paths:
|
||||
# - docs # The path filter somehow does not work, so lets run it on every change to rolling
|
||||
# - webinstaller # The path filter somehow does not work, so lets run it on every change to rolling
|
||||
|
||||
jobs:
|
||||
manually-update-web-installer:
|
||||
@@ -42,13 +42,13 @@ jobs:
|
||||
- name: Add binary to Web Installer and update manifest
|
||||
run: |
|
||||
echo "Updating Web installer to use firmware from ${{ steps.last_release.outputs.tag_name }}..."
|
||||
rm -f docs/binary/firmware.bin
|
||||
wget https://github.com/jomjol/AI-on-the-edge-device/releases/download/${{ steps.last_release.outputs.tag_name }}/AI-on-the-edge-device__update__${{ steps.last_release.outputs.tag_name }}.zip
|
||||
rm -f webinstaller/binary/firmware.bin
|
||||
wget ${{ github.server_url }}/${{ github.repository }}/releases/download/${{ steps.last_release.outputs.tag_name }}/AI-on-the-edge-device__update__${{ steps.last_release.outputs.tag_name }}.zip
|
||||
unzip AI-on-the-edge-device__update__${{ steps.last_release.outputs.tag_name }}.zip
|
||||
cp -f firmware.bin docs/binary/firmware.bin
|
||||
cp -f firmware.bin webinstaller/binary/firmware.bin
|
||||
echo "Updating index and manifest file..."
|
||||
sed -i 's/$VERSION/${{ steps.last_release.outputs.tag_name }}/g' docs/index.html
|
||||
sed -i 's/$VERSION/${{ steps.last_release.outputs.tag_name }}/g' docs/manifest.json
|
||||
sed -i 's/$VERSION/${{ steps.last_release.outputs.tag_name }}/g' webinstaller/index.html
|
||||
sed -i 's/$VERSION/${{ steps.last_release.outputs.tag_name }}/g' webinstaller/manifest.json
|
||||
|
||||
- name: Setup Pages
|
||||
uses: actions/configure-pages@v5
|
||||
@@ -56,7 +56,7 @@ jobs:
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-pages-artifact@v3
|
||||
with:
|
||||
path: 'docs'
|
||||
path: 'webinstaller'
|
||||
|
||||
- name: Deploy to GitHub Pages
|
||||
id: deployment
|
||||
|
||||
7
code/components/allexok_lan/CMakeLists.txt
Normal file
7
code/components/allexok_lan/CMakeLists.txt
Normal file
@@ -0,0 +1,7 @@
|
||||
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)
|
||||
|
||||
|
||||
210
code/components/allexok_lan/connect_lan.cpp
Normal file
210
code/components/allexok_lan/connect_lan.cpp
Normal file
@@ -0,0 +1,210 @@
|
||||
#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(ð_config, ð_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,
|
||||
ð_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
|
||||
20
code/components/allexok_lan/connect_lan.h
Normal file
20
code/components/allexok_lan/connect_lan.h
Normal file
@@ -0,0 +1,20 @@
|
||||
#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
|
||||
248
code/components/allexok_lan/read_lanini.cpp
Normal file
248
code/components/allexok_lan/read_lanini.cpp
Normal file
@@ -0,0 +1,248 @@
|
||||
#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
|
||||
19
code/components/allexok_lan/read_lanini.h
Normal file
19
code/components/allexok_lan/read_lanini.h
Normal file
@@ -0,0 +1,19 @@
|
||||
#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
|
||||
@@ -244,6 +244,10 @@ 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)
|
||||
@@ -1011,7 +1015,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
|
||||
|
||||
|
||||
@@ -230,6 +230,10 @@ 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;
|
||||
@@ -575,6 +579,10 @@ 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]));
|
||||
}
|
||||
|
||||
@@ -37,6 +37,7 @@ protected:
|
||||
|
||||
bool AutoStart;
|
||||
float AutoInterval;
|
||||
bool SleepWhileIdle;
|
||||
void SetInitialParameter(void);
|
||||
std::string aktstatusWithTime;
|
||||
std::string aktstatus;
|
||||
@@ -72,6 +73,7 @@ public:
|
||||
|
||||
bool getIsAutoStart();
|
||||
void setAutoStartInterval(long &_interval);
|
||||
void setSleepWhileIdle(bool& _sleepwhileidle);
|
||||
|
||||
std::string* getActStatusWithTime();
|
||||
std::string* getActStatus();
|
||||
|
||||
@@ -43,6 +43,7 @@ bool bTaskAutoFlowCreated = false;
|
||||
bool flowisrunning = false;
|
||||
|
||||
long auto_interval = 0;
|
||||
bool sleep_while_idle = false;
|
||||
bool autostartIsEnabled = false;
|
||||
|
||||
int countRounds = 0;
|
||||
@@ -1659,6 +1660,7 @@ void task_autodoFlow(void *pvParameter)
|
||||
doInit();
|
||||
|
||||
flowctrl.setAutoStartInterval(auto_interval);
|
||||
flowctrl.setSleepWhileIdle(sleep_while_idle);
|
||||
autostartIsEnabled = flowctrl.getIsAutoStart();
|
||||
|
||||
if (isSetupModusActive())
|
||||
@@ -1739,9 +1741,20 @@ void task_autodoFlow(void *pvParameter)
|
||||
|
||||
if (auto_interval > fr_delta_ms)
|
||||
{
|
||||
const TickType_t xDelay = (auto_interval - fr_delta_ms) / portTICK_PERIOD_MS;
|
||||
ESP_LOGD(TAG, "Autoflow: sleep for: %ldms", (long)xDelay);
|
||||
vTaskDelay(xDelay);
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -644,11 +644,19 @@ 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)
|
||||
{
|
||||
|
||||
@@ -112,8 +112,8 @@ bool SDCardCheckFolderFilePresence()
|
||||
}
|
||||
|
||||
/* check if file exists: wlan.ini */
|
||||
if (stat("/sdcard/wlan.ini", &sb) != 0) {
|
||||
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Folder/file check: File /wlan.ini not found");
|
||||
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");
|
||||
bRetval = false;
|
||||
}
|
||||
|
||||
|
||||
@@ -55,7 +55,7 @@
|
||||
static const char *TAG = "WIFI";
|
||||
|
||||
static bool APWithBetterRSSI = false;
|
||||
static bool WIFIConnected = false;
|
||||
bool WIFIConnected = false;
|
||||
static int WIFIReconnectCnt = 0;
|
||||
|
||||
esp_netif_t *my_sta;
|
||||
|
||||
@@ -14,6 +14,8 @@ 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
|
||||
|
||||
@@ -11,5 +11,5 @@ dependencies:
|
||||
type: idf
|
||||
version: 5.3.1
|
||||
manifest_hash: f88c9e5c2d75a9d5d6968fc67a90ef0cd7146dd6a3905a79c4dfcfc3b4fe6731
|
||||
target: esp32
|
||||
target: esp32s3
|
||||
version: 1.0.0
|
||||
|
||||
@@ -79,6 +79,8 @@
|
||||
//ClassFlowControll + Main + SoftAP
|
||||
#define WLAN_CONFIG_FILE "/sdcard/wlan.ini"
|
||||
|
||||
#define LAN_CONFIG_FILE "/sdcard/lan.ini"
|
||||
|
||||
|
||||
//main
|
||||
#define __SD_USE_ONE_LINE_MODE__
|
||||
@@ -93,8 +95,8 @@
|
||||
|
||||
#define LOGFILE_LAST_PART_BYTES 80 * 1024 // 80 kBytes // Size of partial log file to return
|
||||
|
||||
#define SERVER_FILER_SCRATCH_BUFSIZE 4096
|
||||
#define SERVER_HELPER_SCRATCH_BUFSIZE 4096
|
||||
#define SERVER_FILER_SCRATCH_BUFSIZE 1024
|
||||
#define SERVER_HELPER_SCRATCH_BUFSIZE 1024
|
||||
#define SERVER_OTA_SCRATCH_BUFSIZE 1024
|
||||
|
||||
|
||||
@@ -171,7 +173,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
|
||||
@@ -308,6 +310,63 @@
|
||||
#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
|
||||
|
||||
@@ -25,6 +25,9 @@
|
||||
#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"
|
||||
@@ -213,13 +216,28 @@ 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
|
||||
@@ -448,26 +466,52 @@ extern "C" void app_main(void)
|
||||
ESP_ERROR_CHECK( heap_trace_start(HEAP_TRACE_LEAKS) );
|
||||
#endif
|
||||
|
||||
// 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!");
|
||||
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!");
|
||||
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){
|
||||
|
||||
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!
|
||||
// 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!
|
||||
}
|
||||
}
|
||||
|
||||
xDelay = 2000 / portTICK_PERIOD_MS;
|
||||
@@ -480,7 +524,6 @@ 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);
|
||||
|
||||
@@ -41,6 +41,7 @@
|
||||
|
||||
bool isConfigINI = false;
|
||||
bool isWlanINI = false;
|
||||
bool isLanINI = false;
|
||||
|
||||
static const char *TAG = "WIFI AP";
|
||||
|
||||
@@ -99,12 +100,13 @@ 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 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 += "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 += "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)
|
||||
{
|
||||
@@ -129,33 +131,53 @@ void SendHTTPResponse(httpd_req_t *req)
|
||||
httpd_resp_send_chunk(req, message.c_str(), strlen(message.c_str()));
|
||||
return;
|
||||
}
|
||||
if (!isWlanINI)
|
||||
if (!isWlanINI && !isLanINI)
|
||||
{
|
||||
message = "<h3>2. WLAN access credentials</h3><p>";
|
||||
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 += "<table>";
|
||||
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 += "<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 = "<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>";
|
||||
@@ -207,6 +229,8 @@ 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)
|
||||
@@ -266,27 +290,49 @@ 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 = fopen(WLAN_CONFIG_FILE, "w");
|
||||
FILE* configfilehandle = nullptr;
|
||||
if(type == "wifi"){
|
||||
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
|
||||
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);
|
||||
ssid = "ssid = \"\"\n";
|
||||
fputs(ssid.c_str(), configfilehandle);
|
||||
|
||||
if (pwd.length())
|
||||
pwd = "password = \"" + pwd + "\"\n";
|
||||
else
|
||||
fputs(ssid.c_str(), configfilehandle);
|
||||
pwd = "password = \"\"\n";
|
||||
fputs(pwd.c_str(), configfilehandle);
|
||||
fputs(pwd.c_str(), configfilehandle);
|
||||
}
|
||||
|
||||
text = "\n;++++++++++++++++++++++++++++++++++\n";
|
||||
text += "; Hostname: Name of device in network\n";
|
||||
@@ -333,22 +379,24 @@ esp_err_t config_ini_handler(httpd_req_t *req)
|
||||
dns = ";dns = \"xxx.xxx.xxx.xxx\"\n";
|
||||
fputs(dns.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(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);
|
||||
|
||||
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);
|
||||
@@ -507,14 +555,15 @@ 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)
|
||||
ESP_LOGW(TAG, "wlan.ini not found!");
|
||||
if (!isWlanINI && !isLanINI)
|
||||
ESP_LOGW(TAG, "wlan.ini and lan.ini not found!");
|
||||
|
||||
if (!isConfigINI || !isWlanINI)
|
||||
if (!isConfigINI || (!isWlanINI && !isLanINI))
|
||||
{
|
||||
ESP_LOGI(TAG, "Starting access point for remote configuration");
|
||||
StatusLED(AP_OR_OTA, 2, true);
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
|
||||
[platformio]
|
||||
src_dir = main
|
||||
default_envs = esp32cam
|
||||
default_envs = esp32s3-aleksei
|
||||
|
||||
[common:idf]
|
||||
build_flags =
|
||||
@@ -72,6 +72,31 @@ 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 :)
|
||||
|
||||
2339
code/sdkconfig.esp32s3
Normal file
2339
code/sdkconfig.esp32s3
Normal file
File diff suppressed because it is too large
Load Diff
2339
code/sdkconfig.esp32s3-aleksei
Normal file
2339
code/sdkconfig.esp32s3-aleksei
Normal file
File diff suppressed because it is too large
Load Diff
2337
code/sdkconfig.esp32s3-aleksei.old
Normal file
2337
code/sdkconfig.esp32s3-aleksei.old
Normal file
File diff suppressed because it is too large
Load Diff
5
sd-card/Readme.md
Normal file
5
sd-card/Readme.md
Normal file
@@ -0,0 +1,5 @@
|
||||
# SD Card content
|
||||
This folder contains the files which are required to setup the SD card.
|
||||
|
||||
❗ Do not directly copy this folder onto your SD card, **it will not work!** Instead, you can use any of the artifacts generaded in any of the Pipeline runs of the [Build-Pipeline](https://github.com/jomjol/AI-on-the-edge-device/actions/workflows/build.yaml).
|
||||
The files in the `html` folder here only serve as templates. The real `html` folder get generated using the Github actions.
|
||||
@@ -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]
|
||||
;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
|
||||
[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
|
||||
@@ -43,14 +43,14 @@ AlignmentAlgo = default
|
||||
/config/ref1.jpg 536 113
|
||||
|
||||
[Digits]
|
||||
Model = /config/dig-cont_0710_s3_q.tflite
|
||||
Model = /config/dig-cont_0810_s3_q.tflite
|
||||
CNNGoodThreshold = 0.5
|
||||
;ROIImagesLocation = /log/digit
|
||||
;ROIImagesRetention = 3
|
||||
main.dig1 438 62 49 71 false
|
||||
|
||||
[Analog]
|
||||
Model = /config/ana-cont_1300_s2.tflite
|
||||
Model = /config/ana-cont_1400_s2_q.tflite
|
||||
;ROIImagesLocation = /log/analog
|
||||
;ROIImagesRetention = 3
|
||||
main.ana1 452 199 120 120 false
|
||||
@@ -67,7 +67,7 @@ main.AllowNegativeRates = true
|
||||
main.ExtendedResolution = true
|
||||
main.IgnoreLeadingNaN = false
|
||||
ErrorMessage = true
|
||||
CheckDigitIncreaseConsistency = false
|
||||
main.CheckDigitIncreaseConsistency = false
|
||||
|
||||
;[MQTT]
|
||||
;Uri = mqtt://IP-ADRESS:1883
|
||||
@@ -76,11 +76,14 @@ CheckDigitIncreaseConsistency = false
|
||||
;user = USERNAME
|
||||
;password = PASSWORD
|
||||
RetainMessages = false
|
||||
;DomoticzTopicIn = undefined
|
||||
;main.DomoticzIDX = undefined
|
||||
HomeassistantDiscovery = false
|
||||
;MeterType = other
|
||||
;CACert = /config/certs/RootCA.pem
|
||||
;ClientCert = /config/certs/client.pem.crt
|
||||
;ClientKey = /config/certs/client.pem.key
|
||||
;ValidateServerCert = true
|
||||
|
||||
;[InfluxDB]
|
||||
;Uri = undefined
|
||||
@@ -133,4 +136,3 @@ TimeZone = CET-1CEST,M3.5.0,M10.5.0/3
|
||||
RSSIThreshold = -75
|
||||
CPUFrequency = 160
|
||||
SetupMode = false
|
||||
|
||||
|
||||
@@ -1744,14 +1744,14 @@
|
||||
</tr>
|
||||
<!------------- GPIO4 end ------------------>
|
||||
|
||||
<!------------- GPIO12 begin ------------------>
|
||||
<!------------- GPIO47 begin ------------------>
|
||||
<tr class="GPIO_item">
|
||||
<td class="indent1">
|
||||
<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>
|
||||
<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>
|
||||
</td>
|
||||
<td>
|
||||
<select id="GPIO_IO12_value1">
|
||||
<select id="GPIO_IO47_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_IO12</td>
|
||||
<td>$TOOLTIP_GPIO_IO47</td>
|
||||
</tr>
|
||||
|
||||
<tr class="GPIO_IO12 GPIO_item expert">
|
||||
<tr class="GPIO_IO47 GPIO_item expert">
|
||||
<td class="indent2">
|
||||
<span class="GPIO_IO12 GPIO_item">GPIO12 Use Interrupt</span>
|
||||
<span class="GPIO_IO47 GPIO_item">GPIO47 Use Interrupt</span>
|
||||
</td>
|
||||
<td>
|
||||
<select class="GPIO_IO12 GPIO_item" id="GPIO_IO12_value2">
|
||||
<select class="GPIO_IO47 GPIO_item" id="GPIO_IO47_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_IO12 GPIO_item expert">
|
||||
<tr class="GPIO_IO47 GPIO_item expert">
|
||||
<td class="indent2">
|
||||
<span class="GPIO_IO12 GPIO_item">GPIO12 PWM Duty Cycle Resolution</span>
|
||||
<span class="GPIO_IO47 GPIO_item">GPIO47 PWM Duty Cycle Resolution</span>
|
||||
</td>
|
||||
<td>
|
||||
<input required type="number" id="GPIO_IO12_value3" min="1" max="20"
|
||||
<input required type="number" id="GPIO_IO47_value3" min="1" max="20"
|
||||
oninput="(!validity.rangeUnderflow||(value=1)) && (!validity.rangeOverflow||(value=20)) &&
|
||||
(!validity.stepMismatch||(value=parseInt(this.value)));"><span class="GPIO_IO12 GPIO_item">Bits</span>
|
||||
(!validity.stepMismatch||(value=parseInt(this.value)));"><span class="GPIO_IO47 GPIO_item">Bits</span>
|
||||
</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
|
||||
<tr class="GPIO_IO12 GPIO_item expert">
|
||||
<tr class="GPIO_IO47 GPIO_item expert">
|
||||
<td class="indent2">
|
||||
<span class="GPIO_IO12 GPIO_item">GPIO12 Enable MQTT</span>
|
||||
<span class="GPIO_IO47 GPIO_item">GPIO47 Enable MQTT</span>
|
||||
</td>
|
||||
<td><input type="checkbox" id="GPIO_IO12_value4"></td>
|
||||
<td><input type="checkbox" id="GPIO_IO47_value4"></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
|
||||
<tr class="GPIO_IO12 GPIO_item expert">
|
||||
<tr class="GPIO_IO47 GPIO_item expert">
|
||||
<td class="indent2">
|
||||
<span class="GPIO_IO12 GPIO_item">GPIO12 Enable REST API</span>
|
||||
<span class="GPIO_IO47 GPIO_item">GPIO47 Enable REST API</span>
|
||||
</td>
|
||||
<td><input type="checkbox" id="GPIO_IO12_value5"></td>
|
||||
<td><input type="checkbox" id="GPIO_IO47_value5"></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
|
||||
<tr class="GPIO_IO12 GPIO_item expert">
|
||||
<tr class="GPIO_IO47 GPIO_item expert">
|
||||
<td class="indent2">
|
||||
<span class="GPIO_IO12 GPIO_item">GPIO12 Name</span>
|
||||
<span class="GPIO_IO47 GPIO_item">GPIO47 Name</span>
|
||||
</td>
|
||||
<td><input type="text" id="GPIO_IO12_value6"></td>
|
||||
<td><input type="text" id="GPIO_IO47_value6"></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
|
||||
<tr class="GPIO_item" unused_id="wstypeex3">
|
||||
<td class="indent1">
|
||||
<span class="GPIO_IO12 GPIO_item" id="GPIO_LEDType_text">LED Type (NeoPixel)</span>
|
||||
<span class="GPIO_IO47 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_IO12 GPIO_item" id="GPIO_LEDColor_value1"
|
||||
R <input required type="number" class="GPIO_IO47 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_IO12 GPIO_item" id="GPIO_LEDColor_value2"
|
||||
G <input required type="number" class="GPIO_IO47 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_IO12 GPIO_item" id="GPIO_LEDColor_value3"
|
||||
B <input required type="number" class="GPIO_IO47 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>
|
||||
<!------------- GPIO12 end ------------------>
|
||||
<!------------- GPIO47 end ------------------>
|
||||
|
||||
<!------------- GPIO13 begin ------------------>
|
||||
<tr class="GPIO_IO13 GPIO_item expert">
|
||||
@@ -1974,6 +1974,19 @@
|
||||
<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>
|
||||
@@ -2394,7 +2407,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", "IO12", true);
|
||||
WriteParameter(param, category, "GPIO", "IO47", true);
|
||||
WriteParameter(param, category, "GPIO", "IO13", true);
|
||||
WriteParameter(param, category, "GPIO", "LEDType", false);
|
||||
WriteParameter(param, category, "GPIO", "LEDNumbers", false);
|
||||
@@ -2402,6 +2415,7 @@ 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);
|
||||
@@ -2562,7 +2576,7 @@ function ReadParameterAll() {
|
||||
ReadParameter(param, "GPIO", "IO1", true);
|
||||
ReadParameter(param, "GPIO", "IO3", true);
|
||||
ReadParameter(param, "GPIO", "IO4", true);
|
||||
ReadParameter(param, "GPIO", "IO12", true);
|
||||
ReadParameter(param, "GPIO", "IO47", true);
|
||||
ReadParameter(param, "GPIO", "IO13", true);
|
||||
ReadParameter(param, "GPIO", "LEDType", false);
|
||||
ReadParameter(param, "GPIO", "LEDNumbers", false);
|
||||
@@ -2578,6 +2592,7 @@ 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);
|
||||
@@ -2641,7 +2656,7 @@ function UpdateExpertModus() {
|
||||
}
|
||||
});
|
||||
|
||||
Array.from(document.querySelector("#GPIO_IO12_value1").options).forEach(function(option_element) {
|
||||
Array.from(document.querySelector("#GPIO_IO47_value1").options).forEach(function(option_element) {
|
||||
if (option_element.value != "external-flash-ws281x") {
|
||||
option_element.hidden = _hidden;
|
||||
}
|
||||
|
||||
@@ -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, "IO12", 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, "IO13", 6, false, "", [null, null, /^[0-9]*$/, null, null, /^[a-zA-Z0-9_-]*$/]);
|
||||
ParamAddValue(param, catname, "LEDType");
|
||||
ParamAddValue(param, catname, "LEDNumbers");
|
||||
|
||||
3
webinstaller/Readme.md
Normal file
3
webinstaller/Readme.md
Normal file
@@ -0,0 +1,3 @@
|
||||
# Webinstaller
|
||||
This folder is used to provide the required files to generate the [Web-Installer](https://jomjol.github.io/AI-on-the-edge-device/).
|
||||
The Webinstaller gets automatically updated on a release using the Github actions.
|
||||
2
webinstaller/binary/Readme.md
Normal file
2
webinstaller/binary/Readme.md
Normal file
@@ -0,0 +1,2 @@
|
||||
# Binary folder of the webinstaller
|
||||
The firmware itself (`firmware.bin`) gets copied to this folder through the Github action.
|
||||
@@ -67,21 +67,19 @@
|
||||
|
||||
<div class="footer">
|
||||
<div class="footer-section">
|
||||
<span>Support & Contact Us</span>
|
||||
<span>Support & Contact</span>
|
||||
<a href="https://github.com/jomjol/AI-on-the-edge-device" target="_blank" title="GitHub">
|
||||
<img src="https://github.com/jomjol/AI-on-the-edge-device/images/github-logo.png" alt="GitHub">
|
||||
</a>
|
||||
<img src="https://github.com/jomjol/AI-on-the-edge-device/images/gmail-logo.png" alt="Email">
|
||||
<img src="https://raw.githubusercontent.com/jomjol/AI-on-the-edge-device/refs/heads/main/images/github-logo.png" alt="GitHub">
|
||||
</a>
|
||||
<a href="https://github.com/jomjol/AI-on-the-edge-device/discussions" target="_blank" title="GitHub">
|
||||
<img src="https://github.com/jomjol/AI-on-the-edge-device/images/discussion-logo" alt="GitHub">
|
||||
<img src="https://raw.githubusercontent.com/jomjol/AI-on-the-edge-device/refs/heads/main/images/discussion-logo.png" alt="GitHub">
|
||||
</a>
|
||||
|
||||
</div>
|
||||
<div class="footer-section">
|
||||
<span>Donations</span>
|
||||
<a href="https://www.paypal.com/donate?hosted_button_id=8TRSVYNYKDSWL" target="_blank" title="Donate via PayPal">
|
||||
<img src="https://github.com/jomjol/AI-on-the-edge-device/images/paypal.png" alt="PayPal" style="width: 60px; height: auto;">
|
||||
<img src="https://raw.githubusercontent.com/jomjol/AI-on-the-edge-device/refs/heads/main/images/paypal.png" alt="PayPal" style="width: 60px; height: auto;">
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
Reference in New Issue
Block a user