integrating web stuff into SC-F001
LFG
This commit is contained in:
@@ -2,9 +2,24 @@
|
|||||||
# for more information about component CMakeLists.txt files.
|
# for more information about component CMakeLists.txt files.
|
||||||
|
|
||||||
idf_component_register(
|
idf_component_register(
|
||||||
SRCS main.c i2c.c rtc.c storage.c uart_comms.c control_fsm.c power_mgmt.c rf.c rtc.c sensors.c solar.c # list the source files of this component
|
SRCS main.c i2c.c rtc.c storage.c uart_comms.c control_fsm.c power_mgmt.c rf_433.c rtc.c sensors.c solar.c webserver.c # list the source files of this component
|
||||||
INCLUDE_DIRS # optional, add here public include directories
|
INCLUDE_DIRS # optional, add here public include directories
|
||||||
PRIV_INCLUDE_DIRS # optional, add here private include directories
|
PRIV_INCLUDE_DIRS # optional, add here private include directories
|
||||||
REQUIRES # optional, list the public requirements (component names)
|
REQUIRES # optional, list the public requirements (component names)
|
||||||
PRIV_REQUIRES # optional, list the private requirements
|
PRIV_REQUIRES # optional, list the private requirements
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
if(NOT CMAKE_BUILD_EARLY_EXPANSION)
|
||||||
|
add_custom_command(
|
||||||
|
OUTPUT ${COMPONENT_DIR}/webpage.h
|
||||||
|
COMMAND python ${COMPONENT_DIR}/webpage_compile.py
|
||||||
|
DEPENDS ${COMPONENT_DIR}/landingpage.html ${COMPONENT_DIR}/webpage_compile.py
|
||||||
|
WORKING_DIRECTORY ${COMPONENT_DIR}
|
||||||
|
COMMENT "Generating webpage.h from landingpage.html"
|
||||||
|
VERBATIM
|
||||||
|
)
|
||||||
|
|
||||||
|
add_custom_target(generate_webpage_h DEPENDS ${COMPONENT_DIR}/webpage.h)
|
||||||
|
add_dependencies(${COMPONENT_LIB} generate_webpage_h)
|
||||||
|
endif()
|
||||||
@@ -80,7 +80,7 @@ static inline bool timer_done() { return current_time >= timer_end; }
|
|||||||
|
|
||||||
void pulseOverride(relay_t relay) {
|
void pulseOverride(relay_t relay) {
|
||||||
if (current_state == STATE_IDLE)
|
if (current_state == STATE_IDLE)
|
||||||
override_times[relay] = current_time + get_param(PARAM_RF_PULSE_LENGTH).u64;
|
override_times[relay] = current_time + get_param_value_t(PARAM_RF_PULSE_LENGTH).u64;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*void fsm_begin_auto_move() {
|
/*void fsm_begin_auto_move() {
|
||||||
@@ -120,9 +120,9 @@ int8_t fsm_get_current_progress(int8_t denominator) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#define JACK_TIME get_param(PARAM_JACK_MSPI ).u32 * 1000 * get_param(PARAM_JACK_DIST ).u8
|
#define JACK_TIME get_param_value_t(PARAM_JACK_MSPI ).u32 * 1000 * get_param_value_t(PARAM_JACK_DIST ).u8
|
||||||
#define DRIVE_TIME get_param(PARAM_DRIVE_MSPF).u32 * 1000 * get_param(PARAM_DRIVE_DIST).u8
|
#define DRIVE_TIME get_param_value_t(PARAM_DRIVE_MSPF).u32 * 1000 * get_param_value_t(PARAM_DRIVE_DIST).u8
|
||||||
#define DRIVE_DIST get_param(PARAM_DRIVE_TPDF).u32 / 10 * get_param(PARAM_DRIVE_DIST).u8
|
#define DRIVE_DIST get_param_value_t(PARAM_DRIVE_TPDF).u32 / 10 * get_param_value_t(PARAM_DRIVE_DIST).u8
|
||||||
|
|
||||||
void control_task(void *param) {
|
void control_task(void *param) {
|
||||||
esp_task_wdt_add(NULL);
|
esp_task_wdt_add(NULL);
|
||||||
|
|||||||
328
main/filemgmt.c
328
main/filemgmt.c
@@ -1,328 +0,0 @@
|
|||||||
/*
|
|
||||||
* filemgmt.c
|
|
||||||
*
|
|
||||||
* Created on: Nov 20, 2025
|
|
||||||
* Author: Thad
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "filemgmt.h"
|
|
||||||
#include "endian.h"
|
|
||||||
#include "esp_log.h"
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <inttypes.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <sys/unistd.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include "freertos/FreeRTOS.h"
|
|
||||||
#include "freertos/task.h"
|
|
||||||
#include "freertos/event_groups.h"
|
|
||||||
#include "esp_system.h"
|
|
||||||
#include "esp_mac.h" // for MACSTR
|
|
||||||
#include "esp_wifi.h"
|
|
||||||
#include "esp_event.h"
|
|
||||||
#include "esp_err.h"
|
|
||||||
#include "esp_log.h"
|
|
||||||
#include "esp_vfs.h"
|
|
||||||
#include "nvs_flash.h"
|
|
||||||
#include "esp_vfs_fat.h"
|
|
||||||
#include "esp_littlefs.h"
|
|
||||||
#include "ftp.h"
|
|
||||||
#include "control_fsm.h"
|
|
||||||
#include "power_mgmt.h"
|
|
||||||
#include "rtc.h"
|
|
||||||
#include "sensors.h"
|
|
||||||
|
|
||||||
|
|
||||||
const char* partition_label = "storage";
|
|
||||||
const char *TAG = "MAIN";
|
|
||||||
const char *mount_point = "/root";
|
|
||||||
|
|
||||||
RTC_DATA_ATTR bool find_new_filename = true;
|
|
||||||
|
|
||||||
void start_new_log_file() {
|
|
||||||
find_new_filename = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
EventGroupHandle_t xEventTask;
|
|
||||||
int FTP_TASK_FINISH_BIT = BIT2;
|
|
||||||
|
|
||||||
esp_err_t start_filesystem() {
|
|
||||||
ESP_LOGI(TAG, "Initializing LittleFS on Builtin SPI Flash Memory");
|
|
||||||
|
|
||||||
esp_vfs_littlefs_conf_t conf = {
|
|
||||||
.base_path = mount_point,
|
|
||||||
.partition_label = partition_label,
|
|
||||||
.format_if_mount_failed = true,
|
|
||||||
.dont_mount = false,
|
|
||||||
};
|
|
||||||
|
|
||||||
// Use settings defined above to initialize and mount LittleFS filesystem.
|
|
||||||
// Note: esp_vfs_littlefs_register is an all-in-one convenience function.
|
|
||||||
esp_err_t ret = esp_vfs_littlefs_register(&conf);
|
|
||||||
|
|
||||||
if (ret != ESP_OK) {
|
|
||||||
if (ret == ESP_FAIL) {
|
|
||||||
ESP_LOGE(TAG, "Failed to mount or format filesystem");
|
|
||||||
} else if (ret == ESP_ERR_NOT_FOUND) {
|
|
||||||
ESP_LOGE(TAG, "Failed to find LittleFS partition");
|
|
||||||
} else {
|
|
||||||
ESP_LOGE(TAG, "Failed to initialize LittleFS (%s)", esp_err_to_name(ret));
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t total = 0, used = 0;
|
|
||||||
ret = esp_littlefs_info(conf.partition_label, &total, &used);
|
|
||||||
if (ret != ESP_OK) {
|
|
||||||
ESP_LOGE(TAG, "Failed to get LittleFS partition information (%s)", esp_err_to_name(ret));
|
|
||||||
//esp_littlefs_format(conf.partition_label);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
ESP_LOGI(TAG, "Partition size: total: %d, used: %d", total, used);
|
|
||||||
ESP_LOGI(TAG, "Mount LittleFS on %s", mount_point);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void wifi_event_handler(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data)
|
|
||||||
{
|
|
||||||
if (event_id == WIFI_EVENT_AP_STACONNECTED) {
|
|
||||||
wifi_event_ap_staconnected_t* event = (wifi_event_ap_staconnected_t*) event_data;
|
|
||||||
ESP_LOGI(TAG, "station "MACSTR" join, AID=%d", MAC2STR(event->mac), event->aid);
|
|
||||||
} else if (event_id == WIFI_EVENT_AP_STADISCONNECTED) {
|
|
||||||
wifi_event_ap_stadisconnected_t* event = (wifi_event_ap_stadisconnected_t*) event_data;
|
|
||||||
ESP_LOGI(TAG, "station "MACSTR" leave, AID=%d", MAC2STR(event->mac), event->aid);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extern void ftp_task (void *pvParameters);
|
|
||||||
// Start WiFi AP and FTP Server
|
|
||||||
// filemgmt.c
|
|
||||||
esp_err_t start_ftp_server(void)
|
|
||||||
{
|
|
||||||
ESP_LOGI("FTP", "START");
|
|
||||||
|
|
||||||
close_current_log();
|
|
||||||
|
|
||||||
ESP_ERROR_CHECK(esp_netif_init());
|
|
||||||
ESP_ERROR_CHECK(esp_event_loop_create_default());
|
|
||||||
|
|
||||||
// THIS IS THE CORRECT WAY – recreate the default AP netif every time
|
|
||||||
esp_netif_create_default_wifi_ap();
|
|
||||||
|
|
||||||
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
|
|
||||||
ESP_ERROR_CHECK(esp_wifi_init(&cfg));
|
|
||||||
|
|
||||||
ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT,
|
|
||||||
ESP_EVENT_ANY_ID,
|
|
||||||
&wifi_event_handler,
|
|
||||||
NULL,
|
|
||||||
NULL));
|
|
||||||
|
|
||||||
wifi_config_t wifi_config = {
|
|
||||||
.ap = {
|
|
||||||
.ssid = ESP_WIFI_AP_SSID,
|
|
||||||
.ssid_len = strlen(ESP_WIFI_AP_SSID),
|
|
||||||
.password = ESP_WIFI_AP_PASSWORD,
|
|
||||||
.max_connection = ESP_WIFI_AP_N_CONNECTIONS,
|
|
||||||
.authmode = strlen(ESP_WIFI_AP_PASSWORD) ? WIFI_AUTH_WPA_WPA2_PSK : WIFI_AUTH_OPEN
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_AP));
|
|
||||||
ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_AP, &wifi_config));
|
|
||||||
ESP_ERROR_CHECK(esp_wifi_start());
|
|
||||||
|
|
||||||
ESP_LOGI(TAG, "WiFi AP started – IP 192.168.4.1");
|
|
||||||
|
|
||||||
xEventTask = xEventGroupCreate();
|
|
||||||
xTaskCreate(ftp_task, "FTP", 1024*6, NULL, 2, NULL);
|
|
||||||
|
|
||||||
return ESP_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
void stop_ftp_server(void)
|
|
||||||
{
|
|
||||||
ESP_LOGI("FTP", "OFF");
|
|
||||||
|
|
||||||
ftp_terminate();
|
|
||||||
vTaskDelay(pdMS_TO_TICKS(500)); // give task time to die
|
|
||||||
|
|
||||||
esp_wifi_stop();
|
|
||||||
esp_wifi_deinit();
|
|
||||||
|
|
||||||
// This single call does everything correctly:
|
|
||||||
// Destroy default Wi-Fi interface (handles AP)
|
|
||||||
esp_netif_t *ap_netif = esp_netif_get_handle_from_ifkey("WIFI_AP_DEF");
|
|
||||||
if (ap_netif) {
|
|
||||||
esp_netif_destroy_default_wifi(ap_netif); // Correct API for AP
|
|
||||||
}
|
|
||||||
|
|
||||||
esp_event_loop_delete_default();
|
|
||||||
esp_netif_deinit();
|
|
||||||
|
|
||||||
ESP_LOGI("FTP", "WiFi + FTP completely stopped – safe to restart");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void stop_filesystem() {
|
|
||||||
esp_vfs_littlefs_unregister(partition_label);
|
|
||||||
ESP_LOGI(TAG, "LittleFS unmounted");
|
|
||||||
}
|
|
||||||
|
|
||||||
#define LOG_ENTRY_SIZE 32
|
|
||||||
#define MAX_LOG_FILES 999 // rotate after N files
|
|
||||||
#define ENTRIES_PER_FILE 8000 // ~256 KB per file → safe
|
|
||||||
|
|
||||||
static FILE* logfile = NULL;
|
|
||||||
RTC_DATA_ATTR char current_log_path[32] = "/root/log000.bin";
|
|
||||||
static uint32_t current_entry_count = 0;
|
|
||||||
|
|
||||||
// Helper: close current file safely
|
|
||||||
void close_current_log(void)
|
|
||||||
{
|
|
||||||
if (logfile) {
|
|
||||||
fflush(logfile);
|
|
||||||
fsync(fileno(logfile)); // CRITICAL: forces write to flash
|
|
||||||
fclose(logfile);
|
|
||||||
logfile = NULL;
|
|
||||||
current_entry_count = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Helper: open next log file (rotates 000→009)
|
|
||||||
bool open_next_log_file(void)
|
|
||||||
{
|
|
||||||
close_current_log();
|
|
||||||
|
|
||||||
if (find_new_filename) {
|
|
||||||
// Find next filename
|
|
||||||
for (int i = 0; i < MAX_LOG_FILES; i++) {
|
|
||||||
snprintf(current_log_path, sizeof(current_log_path), "/root/log%03d.bin", i);
|
|
||||||
struct stat st;
|
|
||||||
if (stat(current_log_path, &st) != 0) {
|
|
||||||
break; // file doesn't exist → use this one
|
|
||||||
}
|
|
||||||
if (i == MAX_LOG_FILES-1) {
|
|
||||||
ESP_LOGE("FILE", "RAN OUT OF FILES, GOING TO MAX");
|
|
||||||
// All files exist → overwrite oldest (log000.bin)
|
|
||||||
strcpy(current_log_path, "/root/log999.bin");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
logfile = fopen(current_log_path, "ab"); // binary append
|
|
||||||
if (!logfile) {
|
|
||||||
ESP_LOGE("FILE", "Failed to open %s", current_log_path);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Optional: truncate if too big (safety)
|
|
||||||
fseek(logfile, 0, SEEK_END);
|
|
||||||
if (ftell(logfile) > ENTRIES_PER_FILE * LOG_ENTRY_SIZE) {
|
|
||||||
fclose(logfile);
|
|
||||||
logfile = fopen(current_log_path, "wb"); // truncate
|
|
||||||
}
|
|
||||||
|
|
||||||
find_new_filename = false;
|
|
||||||
} else {
|
|
||||||
logfile = fopen(current_log_path, "ab");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
ESP_LOGI("FILE", "Logging to %s", current_log_path);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void file_log() {
|
|
||||||
if (!logfile && !open_next_log_file()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
char entry[LOG_ENTRY_SIZE] = {0};
|
|
||||||
entry[0] = LOG_ENTRY_SIZE;
|
|
||||||
|
|
||||||
// pack 64-bit timestamp into bytes 1-8
|
|
||||||
uint64_t be_timestamp = htobe64(rtc_time_ms());
|
|
||||||
memcpy(&entry[1], &be_timestamp, 8);
|
|
||||||
|
|
||||||
// pack 32-bit voltages/currents into bytes 9-24
|
|
||||||
int32_t be_voltage = htobe32(get_battery_mV());
|
|
||||||
memcpy(&entry[9], &be_voltage, 4);
|
|
||||||
int32_t be_current1 = htobe32(get_bridge_mA(BRIDGE_DRIVE));
|
|
||||||
memcpy(&entry[13], &be_current1, 4);
|
|
||||||
int32_t be_current2 = htobe32(get_bridge_mA(BRIDGE_JACK));
|
|
||||||
memcpy(&entry[17], &be_current2, 4);
|
|
||||||
int32_t be_current3 = htobe32(get_bridge_mA(BRIDGE_AUX));
|
|
||||||
memcpy(&entry[21], &be_current3, 4);
|
|
||||||
|
|
||||||
|
|
||||||
int32_t be_counter = htobe32(get_sensor_counter(SENSOR_DRIVE));
|
|
||||||
memcpy(&entry[25], &be_counter, 4);
|
|
||||||
|
|
||||||
entry[29] = get_sensor(SENSOR_DRIVE);
|
|
||||||
entry[30] = get_sensor(SENSOR_JACK);
|
|
||||||
entry[31] = fsm_get_state();
|
|
||||||
|
|
||||||
ESP_LOGI("FILE", "LOGGING TO %s: 0x %02x %02x%02x%02x%02x%02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x %02x %02x %02x", current_log_path,
|
|
||||||
entry[0],
|
|
||||||
entry[1],
|
|
||||||
entry[2],
|
|
||||||
entry[3],
|
|
||||||
entry[4],
|
|
||||||
entry[5],
|
|
||||||
entry[6],
|
|
||||||
entry[7],
|
|
||||||
entry[8],
|
|
||||||
entry[9],
|
|
||||||
entry[10],
|
|
||||||
entry[11],
|
|
||||||
entry[12],
|
|
||||||
entry[13],
|
|
||||||
entry[14],
|
|
||||||
entry[15],
|
|
||||||
entry[16],
|
|
||||||
entry[17],
|
|
||||||
entry[18],
|
|
||||||
entry[19],
|
|
||||||
entry[20],
|
|
||||||
entry[21],
|
|
||||||
entry[22],
|
|
||||||
entry[23],
|
|
||||||
entry[24],
|
|
||||||
entry[25],
|
|
||||||
entry[26],
|
|
||||||
entry[27],
|
|
||||||
entry[28],
|
|
||||||
entry[29],
|
|
||||||
entry[30],
|
|
||||||
entry[31]);
|
|
||||||
|
|
||||||
|
|
||||||
/* SEND TO FILE */
|
|
||||||
|
|
||||||
size_t written = fwrite(entry, 1, LOG_ENTRY_SIZE, logfile);
|
|
||||||
if (written != LOG_ENTRY_SIZE) {
|
|
||||||
ESP_LOGE("FILE", "Partial write! Closing file.");
|
|
||||||
close_current_log();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
current_entry_count++;
|
|
||||||
|
|
||||||
// Periodic flush (every 50–100 entries) + full sync every 500
|
|
||||||
if (current_entry_count % 100 == 0) {
|
|
||||||
fflush(logfile);
|
|
||||||
}
|
|
||||||
if (current_entry_count % 500 == 0) {
|
|
||||||
fsync(fileno(logfile));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Rotate if getting large
|
|
||||||
if (current_entry_count >= ENTRIES_PER_FILE) {
|
|
||||||
ESP_LOGI("FILE", "Rotating log file");
|
|
||||||
open_next_log_file();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
/*
|
|
||||||
* filemgmt.h
|
|
||||||
*
|
|
||||||
* Created on: Nov 20, 2025
|
|
||||||
* Author: Thad
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef MAIN_FILEMGMT_H_
|
|
||||||
#define MAIN_FILEMGMT_H_
|
|
||||||
|
|
||||||
#include "esp_err.h"
|
|
||||||
|
|
||||||
|
|
||||||
#define ESP_WIFI_AP_SSID "stockcropper"
|
|
||||||
#define ESP_WIFI_AP_PASSWORD ""
|
|
||||||
#define ESP_WIFI_AP_N_CONNECTIONS 4
|
|
||||||
|
|
||||||
// Open the filesystem (e.g. for logging)
|
|
||||||
esp_err_t start_filesystem();
|
|
||||||
|
|
||||||
// Start WiFi AP and FTP Server
|
|
||||||
esp_err_t start_ftp_server();
|
|
||||||
|
|
||||||
void stop_filesystem();
|
|
||||||
void stop_ftp_server();
|
|
||||||
|
|
||||||
void file_log();
|
|
||||||
|
|
||||||
void close_current_log();
|
|
||||||
|
|
||||||
void start_new_log_file();
|
|
||||||
|
|
||||||
#endif /* MAIN_FILEMGMT_H_ */
|
|
||||||
1413
main/ftp.c
1413
main/ftp.c
File diff suppressed because it is too large
Load Diff
214
main/ftp.h
214
main/ftp.h
@@ -1,214 +0,0 @@
|
|||||||
/*
|
|
||||||
* This file is part of the MicroPython ESP32 project, https://github.com/loboris/MicroPython_ESP32_psRAM_LoBo
|
|
||||||
*
|
|
||||||
* The MIT License (MIT)
|
|
||||||
*
|
|
||||||
* Copyright (c) 2018 LoBo (https://github.com/loboris)
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
|
||||||
* in the Software without restriction, including without limitation the rights
|
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
|
||||||
* furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included in
|
|
||||||
* all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
||||||
* THE SOFTWARE.
|
|
||||||
*/
|
|
||||||
/*
|
|
||||||
* This file is based on 'ftp' from Pycom Limited.
|
|
||||||
*
|
|
||||||
* Author: LoBo, loboris@gmail.com
|
|
||||||
* Copyright (c) 2017, LoBo
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef FTP_H_
|
|
||||||
#define FTP_H_
|
|
||||||
|
|
||||||
#include "sdkconfig.h"
|
|
||||||
#include "freertos/FreeRTOS.h"
|
|
||||||
#include "freertos/queue.h"
|
|
||||||
#include "sys/dirent.h"
|
|
||||||
|
|
||||||
/******************************************************************************
|
|
||||||
DEFINE PRIVATE CONSTANTS
|
|
||||||
******************************************************************************/
|
|
||||||
#define FTP_CMD_PORT 21
|
|
||||||
#define FTP_ACTIVE_DATA_PORT 20
|
|
||||||
#define FTP_PASIVE_DATA_PORT 2024
|
|
||||||
#define FTP_CMD_SIZE_MAX 6
|
|
||||||
#define FTP_CMD_CLIENTS_MAX 1
|
|
||||||
#define FTP_DATA_CLIENTS_MAX 1
|
|
||||||
#define FTP_MAX_PARAM_SIZE (MICROPY_ALLOC_PATH_MAX + 1)
|
|
||||||
#define FTP_UNIX_SECONDS_180_DAYS 15552000
|
|
||||||
#define FTP_DATA_TIMEOUT_MS 10000 // 10 seconds
|
|
||||||
#define FTP_SOCKETFIFO_ELEMENTS_MAX 4
|
|
||||||
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
E_FTP_STE_DISABLED = 0,
|
|
||||||
E_FTP_STE_START,
|
|
||||||
E_FTP_STE_READY,
|
|
||||||
E_FTP_STE_END_TRANSFER,
|
|
||||||
E_FTP_STE_CONTINUE_LISTING,
|
|
||||||
E_FTP_STE_CONTINUE_FILE_TX,
|
|
||||||
E_FTP_STE_CONTINUE_FILE_RX,
|
|
||||||
E_FTP_STE_CONNECTED
|
|
||||||
} ftp_state_t;
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
E_FTP_STE_SUB_DISCONNECTED = 0,
|
|
||||||
E_FTP_STE_SUB_LISTEN_FOR_DATA,
|
|
||||||
E_FTP_STE_SUB_DATA_CONNECTED
|
|
||||||
} ftp_substate_t;
|
|
||||||
|
|
||||||
|
|
||||||
/******************************************************************************
|
|
||||||
DEFINE PRIVATE TYPES
|
|
||||||
******************************************************************************/
|
|
||||||
typedef enum {
|
|
||||||
E_FTP_RESULT_OK = 0,
|
|
||||||
E_FTP_RESULT_CONTINUE,
|
|
||||||
E_FTP_RESULT_FAILED
|
|
||||||
} ftp_result_t;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
bool uservalid : 1;
|
|
||||||
bool passvalid : 1;
|
|
||||||
} ftp_loggin_t;
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
E_FTP_NOTHING_OPEN = 0,
|
|
||||||
E_FTP_FILE_OPEN,
|
|
||||||
E_FTP_DIR_OPEN
|
|
||||||
} ftp_e_open_t;
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
E_FTP_CLOSE_NONE = 0,
|
|
||||||
E_FTP_CLOSE_DATA,
|
|
||||||
E_FTP_CLOSE_CMD_AND_DATA,
|
|
||||||
} ftp_e_closesocket_t;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
uint8_t *dBuffer;
|
|
||||||
uint32_t ctimeout;
|
|
||||||
union {
|
|
||||||
DIR *dp;
|
|
||||||
FILE *fp;
|
|
||||||
};
|
|
||||||
int32_t lc_sd;
|
|
||||||
int32_t ld_sd;
|
|
||||||
int32_t c_sd;
|
|
||||||
int32_t d_sd;
|
|
||||||
int32_t dtimeout;
|
|
||||||
uint32_t ip_addr;
|
|
||||||
uint8_t state;
|
|
||||||
uint8_t substate;
|
|
||||||
uint8_t txRetries;
|
|
||||||
uint8_t logginRetries;
|
|
||||||
ftp_loggin_t loggin;
|
|
||||||
uint8_t e_open;
|
|
||||||
bool closechild;
|
|
||||||
bool enabled;
|
|
||||||
bool listroot;
|
|
||||||
uint32_t total;
|
|
||||||
uint32_t time;
|
|
||||||
} ftp_data_t;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
char * cmd;
|
|
||||||
} ftp_cmd_t;
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
E_FTP_CMD_NOT_SUPPORTED = -1,
|
|
||||||
E_FTP_CMD_FEAT = 0,
|
|
||||||
E_FTP_CMD_SYST,
|
|
||||||
E_FTP_CMD_CDUP,
|
|
||||||
E_FTP_CMD_CWD,
|
|
||||||
E_FTP_CMD_PWD,
|
|
||||||
E_FTP_CMD_XPWD,
|
|
||||||
E_FTP_CMD_SIZE,
|
|
||||||
E_FTP_CMD_MDTM,
|
|
||||||
E_FTP_CMD_TYPE,
|
|
||||||
E_FTP_CMD_USER,
|
|
||||||
E_FTP_CMD_PASS,
|
|
||||||
E_FTP_CMD_PASV,
|
|
||||||
E_FTP_CMD_LIST,
|
|
||||||
E_FTP_CMD_RETR,
|
|
||||||
E_FTP_CMD_STOR,
|
|
||||||
E_FTP_CMD_DELE,
|
|
||||||
E_FTP_CMD_RMD,
|
|
||||||
E_FTP_CMD_MKD,
|
|
||||||
E_FTP_CMD_RNFR,
|
|
||||||
E_FTP_CMD_RNTO,
|
|
||||||
E_FTP_CMD_NOOP,
|
|
||||||
E_FTP_CMD_QUIT,
|
|
||||||
E_FTP_CMD_APPE,
|
|
||||||
E_FTP_CMD_NLST,
|
|
||||||
E_FTP_CMD_AUTH,
|
|
||||||
E_FTP_NUM_FTP_CMDS
|
|
||||||
} ftp_cmd_index_t;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#define FTP_USER_PASS_LEN_MAX 32
|
|
||||||
#define FTP_DEF_USER "micro"
|
|
||||||
#define FTP_DEF_PASS "python"
|
|
||||||
#define FTP_MUTEX_TIMEOUT_MS 1000
|
|
||||||
#define FTP_CMD_TIMEOUT_MS (CONFIG_MICROPY_FTPSERVER_TIMEOUT*1000)
|
|
||||||
|
|
||||||
#define CONFIG_MICROPY_FTPSERVER_BUFFER_SIZE 1024
|
|
||||||
#define CONFIG_MICROPY_FTPSERVER_TIMEOUT 300
|
|
||||||
#define ONFIG_MICROPY_FILESYSTEM_TYPE 0
|
|
||||||
#define MICROPY_ALLOC_PATH_MAX (512)
|
|
||||||
|
|
||||||
// #define MAX_ACTIVE_INTERFACES 3
|
|
||||||
//tcpip_adapter_if_t tcpip_if[MAX_ACTIVE_INTERFACES] = {TCPIP_ADAPTER_IF_MAX};
|
|
||||||
|
|
||||||
#define VFS_NATIVE_MOUNT_POINT "/_#!#_spiffs"
|
|
||||||
#define VFS_NATIVE_SDCARD_MOUNT_POINT "/_#!#_sdcard"
|
|
||||||
#define VFS_NATIVE_INTERNAL_PART_LABEL "internalfs"
|
|
||||||
#define VFS_NATIVE_INTERNAL_MP "/flash"
|
|
||||||
#define VFS_NATIVE_EXTERNAL_MP "/sd"
|
|
||||||
#define VFS_NATIVE_TYPE_SPIFLASH 0
|
|
||||||
#define VFS_NATIVE_TYPE_SDCARD 1
|
|
||||||
|
|
||||||
#ifndef MIN
|
|
||||||
#define MIN(x, y) ((x) < (y) ? (x) : (y))
|
|
||||||
#endif
|
|
||||||
#ifndef MAX
|
|
||||||
#define MAX(x, y) ((x) > (y) ? (x) : (y))
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
extern const char *FTP_TAG;
|
|
||||||
extern char ftp_user[FTP_USER_PASS_LEN_MAX + 1];
|
|
||||||
extern char ftp_pass[FTP_USER_PASS_LEN_MAX + 1];
|
|
||||||
extern uint32_t ftp_stack_size;
|
|
||||||
extern QueueHandle_t ftp_mutex;
|
|
||||||
extern int ftp_buff_size;
|
|
||||||
extern int ftp_timeout;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
bool ftp_init (void);
|
|
||||||
void ftp_deinit (void);
|
|
||||||
int ftp_run (uint32_t elapsed);
|
|
||||||
bool ftp_enable (void);
|
|
||||||
bool ftp_isenabled (void);
|
|
||||||
bool ftp_disable (void);
|
|
||||||
bool ftp_reset (void);
|
|
||||||
int ftp_getstate();
|
|
||||||
bool ftp_terminate (void);
|
|
||||||
bool ftp_stop_requested();
|
|
||||||
int32_t ftp_get_maxstack (void);
|
|
||||||
uint64_t mp_hal_ticks_ms(void);
|
|
||||||
|
|
||||||
#endif /* FTP_H_ */
|
|
||||||
159
main/landingpage.html
Normal file
159
main/landingpage.html
Normal file
@@ -0,0 +1,159 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Control Panel</title>
|
||||||
|
<style>
|
||||||
|
* { background-color: #111; color: #eee; font-family: sans-serif; }
|
||||||
|
input { border: 1px solid #666; background-color: #333; font-family: monospace; text-align: right; width: 100%; box-sizing: border-box; }
|
||||||
|
.changed { background-color: #3d3 !important; color: #111 !important; }
|
||||||
|
#commit_btn { width: 100%; background-color: #3d3; color: #111; margin-top: 10px; padding: 10px; cursor: pointer; border: none; font-weight: bold; }
|
||||||
|
#commit_btn[disabled] { background-color: #444; color: #888; cursor: not-allowed; }
|
||||||
|
table { width: 100%; border-collapse: collapse; }
|
||||||
|
td { padding: 8px; border-bottom: 1px solid #222; }
|
||||||
|
tr:hover { background-color: #1a1a1a; }
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<table id="table">
|
||||||
|
<tr>
|
||||||
|
<td>-</td>
|
||||||
|
<td>System Time</td>
|
||||||
|
<td><input type="datetime-local" id="in_time" step="1" onchange="markChanged(this)"/></td>
|
||||||
|
<td></td>
|
||||||
|
</tr>
|
||||||
|
<tr><td colspan="4"><button id="commit_btn" onclick="commit_params()" disabled>Save Changes</button></td></tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<input type="file" id="firmware_file" accept=".bin">
|
||||||
|
<button id="upload_btn" onclick="uploadFirmware()">Upload Firmware</button>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
let param_values = [];
|
||||||
|
const param_names = ["Drive Distance", "TPDF", "Efuse Amt", "Gain", "Offset"];
|
||||||
|
const param_units = ["in", "ft", "in", "V", "ms"];
|
||||||
|
|
||||||
|
function ge(x) { return document.getElementById(x); }
|
||||||
|
|
||||||
|
// Highlight changed inputs and enable the save button
|
||||||
|
function markChanged(el) {
|
||||||
|
el.classList.add("changed");
|
||||||
|
ge('commit_btn').disabled = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- 1. GET DATA ---
|
||||||
|
function fetchStatus() {
|
||||||
|
const xhr = new XMLHttpRequest();
|
||||||
|
xhr.open("GET", "http://192.168.4.1/status", true);
|
||||||
|
xhr.onload = function() {
|
||||||
|
if (xhr.status === 200) {
|
||||||
|
try {
|
||||||
|
console.log(xhr.responseText);
|
||||||
|
const data = JSON.parse(xhr.responseText);
|
||||||
|
|
||||||
|
// Update time field if available
|
||||||
|
if(data.time) {
|
||||||
|
const date = new Date(data.time * 1000).toISOString().slice(0, 19);
|
||||||
|
ge('in_time').value = date;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Store values (default to empty array if missing)
|
||||||
|
param_values = data.params || [];
|
||||||
|
} catch(e) {
|
||||||
|
console.error("Error parsing JSON", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Always render table even if request fails or data is empty
|
||||||
|
renderTable();
|
||||||
|
};
|
||||||
|
xhr.onerror = function(e) {
|
||||||
|
console.error("Network error", e);
|
||||||
|
renderTable();
|
||||||
|
};
|
||||||
|
xhr.send();
|
||||||
|
}
|
||||||
|
|
||||||
|
function renderTable() {
|
||||||
|
const table = ge("table");
|
||||||
|
// Clear existing parameter rows (rows between index 0 and the last row)
|
||||||
|
while(table.rows.length > 2) { table.deleteRow(1); }
|
||||||
|
|
||||||
|
// Loop through the NAMES array to ensure every input is shown
|
||||||
|
param_names.forEach((name, i) => {
|
||||||
|
let row = table.insertRow(table.rows.length - 1);
|
||||||
|
|
||||||
|
// If the server didn't send a value for this index, show "null"
|
||||||
|
let val = (param_values[i] !== undefined && param_values[i] !== null)
|
||||||
|
? param_values[i]
|
||||||
|
: "null";
|
||||||
|
|
||||||
|
row.innerHTML = `
|
||||||
|
<td>${i}</td>
|
||||||
|
<td>${name}</td>
|
||||||
|
<td><input type="text" id="in_${i}" value="${val}" oninput="markChanged(this)"></td>
|
||||||
|
<td>${param_units[i] || ""}</td>
|
||||||
|
`;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- 2. POST DATA ---
|
||||||
|
function commit_params() {
|
||||||
|
ge('commit_btn').disabled = true;
|
||||||
|
const changedInputs = document.querySelectorAll('input.changed');
|
||||||
|
|
||||||
|
changedInputs.forEach(input => {
|
||||||
|
const xhr = new XMLHttpRequest();
|
||||||
|
|
||||||
|
if (input.id === "in_time") {
|
||||||
|
// Time handling
|
||||||
|
const epoch = Math.floor(new Date(input.value).getTime() / 1000);
|
||||||
|
xhr.open("POST", "http://192.168.4.1/st", true);
|
||||||
|
xhr.setRequestHeader("Content-Type", "application/json");
|
||||||
|
xhr.send(JSON.stringify({ time: epoch }));
|
||||||
|
input.classList.remove("changed");
|
||||||
|
} else {
|
||||||
|
// Parameter handling
|
||||||
|
const id = input.id.split('_')[1];
|
||||||
|
// If the user typed "null", we send null; otherwise parse as float
|
||||||
|
const val = (input.value.toLowerCase() === "null") ? null : parseFloat(input.value);
|
||||||
|
|
||||||
|
xhr.open("POST", "/sp", true);
|
||||||
|
xhr.setRequestHeader("Content-Type", "application/json");
|
||||||
|
xhr.onload = function() {
|
||||||
|
if (xhr.status === 200) {
|
||||||
|
input.classList.remove("changed");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
xhr.send(JSON.stringify({ id: parseInt(id), value: val }));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function uploadFirmware() {
|
||||||
|
const fileInput = ge('firmware_file');
|
||||||
|
if (!fileInput.files.length) {
|
||||||
|
alert('No file selected');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const file = fileInput.files[0];
|
||||||
|
const xhr = new XMLHttpRequest();
|
||||||
|
xhr.open("POST", "http://192.168.4.1/ota", true);
|
||||||
|
xhr.setRequestHeader("Content-Type", "application/octet-stream");
|
||||||
|
xhr.onload = function() {
|
||||||
|
if (xhr.status === 200) {
|
||||||
|
alert('Upload successful. Device may reboot.');
|
||||||
|
} else {
|
||||||
|
alert('Upload failed: ' + xhr.status);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
xhr.onerror = function() {
|
||||||
|
alert('Network error during upload');
|
||||||
|
};
|
||||||
|
xhr.send(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initial Load
|
||||||
|
window.onload = fetchStatus;
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -10,7 +10,8 @@
|
|||||||
#include "rtc.h"
|
#include "rtc.h"
|
||||||
#include "sensors.h"
|
#include "sensors.h"
|
||||||
#include "solar.h"
|
#include "solar.h"
|
||||||
#include "rf.h"
|
#include "rf_433.h"
|
||||||
|
#include "webserver.h"
|
||||||
|
|
||||||
#define TAG "MAIN"
|
#define TAG "MAIN"
|
||||||
|
|
||||||
@@ -140,9 +141,10 @@ void app_main(void) {
|
|||||||
/*** FULL BOOT ***/
|
/*** FULL BOOT ***/
|
||||||
if (uart_init() != ESP_OK) ESP_LOGE(TAG, "UART FAILED");
|
if (uart_init() != ESP_OK) ESP_LOGE(TAG, "UART FAILED");
|
||||||
if (power_init() != ESP_OK) ESP_LOGE(TAG, "POWER FAILED");
|
if (power_init() != ESP_OK) ESP_LOGE(TAG, "POWER FAILED");
|
||||||
if (rf_init() != ESP_OK) ESP_LOGE(TAG, "RF FAILED");
|
if (rf_433_init() != ESP_OK) ESP_LOGE(TAG, "RF FAILED");
|
||||||
if (fsm_init() != ESP_OK) ESP_LOGE(TAG, "FSM FAILED");
|
if (fsm_init() != ESP_OK) ESP_LOGE(TAG, "FSM FAILED");
|
||||||
if (sensors_init() != ESP_OK) ESP_LOGE(TAG, "SENSORS FAILED");
|
if (sensors_init() != ESP_OK) ESP_LOGE(TAG, "SENSORS FAILED");
|
||||||
|
if (webserver_init() != ESP_OK) ESP_LOGE(TAG, "WEBSERVER FAILED");
|
||||||
|
|
||||||
/*** MAIN LOOP ***/
|
/*** MAIN LOOP ***/
|
||||||
|
|
||||||
|
|||||||
@@ -123,7 +123,7 @@ esp_err_t process_battery_voltage(void)
|
|||||||
ema_battery = (float)raw;
|
ema_battery = (float)raw;
|
||||||
ema_battery_init = true;
|
ema_battery_init = true;
|
||||||
} else {
|
} else {
|
||||||
float alpha = get_param(PARAM_ADC_ALPHA_BATTERY).f32;
|
float alpha = get_param_value_t(PARAM_ADC_ALPHA_BATTERY).f32;
|
||||||
if (isnan(raw)) {
|
if (isnan(raw)) {
|
||||||
ESP_LOGI(TAG, "RAW BATTERY IS NAN");
|
ESP_LOGI(TAG, "RAW BATTERY IS NAN");
|
||||||
} else {
|
} else {
|
||||||
@@ -182,7 +182,7 @@ esp_err_t process_bridge_current(bridge_t bridge) {
|
|||||||
channel->ema_current = (float)raw_a;
|
channel->ema_current = (float)raw_a;
|
||||||
channel->ema_init = true;
|
channel->ema_init = true;
|
||||||
} else {
|
} else {
|
||||||
float alpha = get_param(PARAM_ADC_ALPHA_ISENS).f32;
|
float alpha = get_param_value_t(PARAM_ADC_ALPHA_ISENS).f32;
|
||||||
if (isnan(raw_a)) {
|
if (isnan(raw_a)) {
|
||||||
ESP_LOGI(TAG, "RAW BATTERY IS NAN");
|
ESP_LOGI(TAG, "RAW BATTERY IS NAN");
|
||||||
channel->ema_current = NAN;
|
channel->ema_current = NAN;
|
||||||
@@ -197,14 +197,14 @@ esp_err_t process_bridge_current(bridge_t bridge) {
|
|||||||
// === AUTO-ZERO LEARNING PHASE ===
|
// === AUTO-ZERO LEARNING PHASE ===
|
||||||
if (now > channel->az_enable_time) {
|
if (now > channel->az_enable_time) {
|
||||||
//ESP_LOGI(TAG, "AZING %d", bridge);
|
//ESP_LOGI(TAG, "AZING %d", bridge);
|
||||||
float db = get_param(PARAM_ADC_DB_IAZ).f32;
|
float db = get_param_value_t(PARAM_ADC_DB_IAZ).f32;
|
||||||
if (isnan(db) || fabsf(channel->ema_current) <= db) {
|
if (isnan(db) || fabsf(channel->ema_current) <= db) {
|
||||||
// Valid zero sample
|
// Valid zero sample
|
||||||
if (!channel->az_initialized) {
|
if (!channel->az_initialized) {
|
||||||
channel->az_offset = channel->ema_current;
|
channel->az_offset = channel->ema_current;
|
||||||
channel->az_initialized = true;
|
channel->az_initialized = true;
|
||||||
} else {
|
} else {
|
||||||
float alpha = get_param(PARAM_ADC_ALPHA_IAZ).f32;
|
float alpha = get_param_value_t(PARAM_ADC_ALPHA_IAZ).f32;
|
||||||
if (isnan(raw_a)) {
|
if (isnan(raw_a)) {
|
||||||
ESP_LOGI(TAG, "RAW BATTERY IS NAN");
|
ESP_LOGI(TAG, "RAW BATTERY IS NAN");
|
||||||
} else {
|
} else {
|
||||||
@@ -231,13 +231,13 @@ esp_err_t process_bridge_current(bridge_t bridge) {
|
|||||||
float I_nominal = NAN;
|
float I_nominal = NAN;
|
||||||
switch(bridge) {
|
switch(bridge) {
|
||||||
case BRIDGE_DRIVE:
|
case BRIDGE_DRIVE:
|
||||||
I_nominal = get_param(PARAM_EFUSE_INOM_1).f32;
|
I_nominal = get_param_value_t(PARAM_EFUSE_INOM_1).f32;
|
||||||
break;
|
break;
|
||||||
case BRIDGE_JACK:
|
case BRIDGE_JACK:
|
||||||
I_nominal = get_param(PARAM_EFUSE_INOM_2).f32;
|
I_nominal = get_param_value_t(PARAM_EFUSE_INOM_2).f32;
|
||||||
break;
|
break;
|
||||||
case BRIDGE_AUX:
|
case BRIDGE_AUX:
|
||||||
I_nominal = get_param(PARAM_EFUSE_INOM_3).f32;
|
I_nominal = get_param_value_t(PARAM_EFUSE_INOM_3).f32;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -245,7 +245,7 @@ esp_err_t process_bridge_current(bridge_t bridge) {
|
|||||||
float I_norm = fabsf(channel->current / I_nominal);
|
float I_norm = fabsf(channel->current / I_nominal);
|
||||||
|
|
||||||
// Instant trip on extreme overcurrent
|
// Instant trip on extreme overcurrent
|
||||||
if (I_norm >= get_param(PARAM_EFUSE_KINST).f32) {
|
if (I_norm >= get_param_value_t(PARAM_EFUSE_KINST).f32) {
|
||||||
channel->tripped = true;
|
channel->tripped = true;
|
||||||
channel->trip_time = now;
|
channel->trip_time = now;
|
||||||
ESP_LOGI(TAG, "FUSE TRIP: Inom: %+.5f HEAT:%+2.5f", I_norm, channel->heat);
|
ESP_LOGI(TAG, "FUSE TRIP: Inom: %+.5f HEAT:%+2.5f", I_norm, channel->heat);
|
||||||
@@ -259,7 +259,7 @@ esp_err_t process_bridge_current(bridge_t bridge) {
|
|||||||
if (I_norm < 1.0f) {
|
if (I_norm < 1.0f) {
|
||||||
// if we are hot we radiate more heat
|
// if we are hot we radiate more heat
|
||||||
// (I^2/I^2*t) * (1/t) * t = I^2/I^2*t
|
// (I^2/I^2*t) * (1/t) * t = I^2/I^2*t
|
||||||
channel->heat -= channel->heat * get_param(PARAM_EFUSE_TAUCOOL).f32 * UPDATE_S;
|
channel->heat -= channel->heat * get_param_value_t(PARAM_EFUSE_TAUCOOL).f32 * UPDATE_S;
|
||||||
channel->heat = fmaxf(0.0f, channel->heat); // keep it from going negative
|
channel->heat = fmaxf(0.0f, channel->heat); // keep it from going negative
|
||||||
// channel.tripped = false; // Auto-clear if cooled (WTF why this is insane)
|
// channel.tripped = false; // Auto-clear if cooled (WTF why this is insane)
|
||||||
}
|
}
|
||||||
@@ -267,7 +267,7 @@ esp_err_t process_bridge_current(bridge_t bridge) {
|
|||||||
// If built-up heat exceeds the time limit, trip
|
// If built-up heat exceeds the time limit, trip
|
||||||
// Recall units of heat are (current_actual^2/current_nominal^2)*time
|
// Recall units of heat are (current_actual^2/current_nominal^2)*time
|
||||||
// Ergo, heat is measured in seconds
|
// Ergo, heat is measured in seconds
|
||||||
if (channel->heat > get_param(PARAM_EFUSE_HEAT_THRESH).f32) {
|
if (channel->heat > get_param_value_t(PARAM_EFUSE_HEAT_THRESH).f32) {
|
||||||
channel->tripped = true;
|
channel->tripped = true;
|
||||||
channel->trip_time = now;
|
channel->trip_time = now;
|
||||||
|
|
||||||
@@ -275,7 +275,7 @@ esp_err_t process_bridge_current(bridge_t bridge) {
|
|||||||
// And enough time has passed
|
// And enough time has passed
|
||||||
// Go ahead and reset the e-fuse
|
// Go ahead and reset the e-fuse
|
||||||
} else if (channel->tripped &&
|
} else if (channel->tripped &&
|
||||||
(now - channel->trip_time) > get_param(PARAM_EFUSE_TCOOL).i64) {
|
(now - channel->trip_time) > get_param_value_t(PARAM_EFUSE_TCOOL).i64) {
|
||||||
channel->tripped = false;
|
channel->tripped = false;
|
||||||
// channel.heat = 0.0f // I think we should wait for the e-fuse to catch up
|
// channel.heat = 0.0f // I think we should wait for the e-fuse to catch up
|
||||||
}
|
}
|
||||||
|
|||||||
30
main/rf.h
30
main/rf.h
@@ -1,30 +0,0 @@
|
|||||||
|
|
||||||
#ifndef RF_H
|
|
||||||
#define RF_H
|
|
||||||
|
|
||||||
#include <inttypes.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
|
|
||||||
#include "freertos/FreeRTOS.h"
|
|
||||||
#include "freertos/task.h"
|
|
||||||
#include "freertos/queue.h"
|
|
||||||
|
|
||||||
#define NUM_RF_BUTTONS 8
|
|
||||||
|
|
||||||
int64_t recieveKeycode();
|
|
||||||
|
|
||||||
esp_err_t rf_init();
|
|
||||||
esp_err_t rf_stop();
|
|
||||||
|
|
||||||
void rf_set_keycode(uint8_t index, int64_t code);
|
|
||||||
|
|
||||||
int8_t rf_get_keycode();
|
|
||||||
int64_t rf_get_raw_keycode();
|
|
||||||
|
|
||||||
void rf_clear_queue();
|
|
||||||
|
|
||||||
void rf_learn_keycode(uint8_t index);
|
|
||||||
void rf_cancel_learn_keycode();
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -15,7 +15,7 @@
|
|||||||
#include "driver/rmt_rx.h"
|
#include "driver/rmt_rx.h"
|
||||||
#include "driver/gpio.h"
|
#include "driver/gpio.h"
|
||||||
#include "esp_log.h"
|
#include "esp_log.h"
|
||||||
#include "rf.h"
|
#include "rf_433.h"
|
||||||
|
|
||||||
#include "storage.h"
|
#include "storage.h"
|
||||||
|
|
||||||
@@ -51,7 +51,7 @@ static bool rfrx_done(rmt_channel_handle_t channel, const rmt_rx_done_event_data
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Task that receives and decodes RF signals
|
// Task that receives and decodes RF signals
|
||||||
static void rf_receiver_task(void* param) {
|
static void rf_433_receiver_task(void* param) {
|
||||||
esp_task_wdt_add(NULL);
|
esp_task_wdt_add(NULL);
|
||||||
esp_log_level_set("rmt", ESP_LOG_NONE); // disable rmt messages about hw buffer too small
|
esp_log_level_set("rmt", ESP_LOG_NONE); // disable rmt messages about hw buffer too small
|
||||||
const uint16_t tlow = (P_HIGH - P_LOW - (2 * P_MARGIN));
|
const uint16_t tlow = (P_HIGH - P_LOW - (2 * P_MARGIN));
|
||||||
@@ -137,7 +137,7 @@ static void rf_receiver_task(void* param) {
|
|||||||
ESP_LOGI(TAG, "GOT KEYCODE 0x%lx [%d]", (long) code, len);
|
ESP_LOGI(TAG, "GOT KEYCODE 0x%lx [%d]", (long) code, len);
|
||||||
|
|
||||||
if (learn_flag >= 0) {
|
if (learn_flag >= 0) {
|
||||||
set_param(PARAM_KEYCODE_0 + learn_flag,
|
set_param_value_t(PARAM_KEYCODE_0 + learn_flag,
|
||||||
(param_value_t){.i64 = encoded});
|
(param_value_t){.i64 = encoded});
|
||||||
ESP_LOGI(TAG, "LEARNED KEYCODE");
|
ESP_LOGI(TAG, "LEARNED KEYCODE");
|
||||||
learn_flag = -1;
|
learn_flag = -1;
|
||||||
@@ -156,7 +156,7 @@ static void rf_receiver_task(void* param) {
|
|||||||
|
|
||||||
|
|
||||||
for (uint8_t i = 0; i < NUM_RF_BUTTONS; i++) {
|
for (uint8_t i = 0; i < NUM_RF_BUTTONS; i++) {
|
||||||
int64_t match = get_param(PARAM_KEYCODE_0+i).i64;
|
int64_t match = get_param_value_t(PARAM_KEYCODE_0+i).i64;
|
||||||
if (encoded == match) {
|
if (encoded == match) {
|
||||||
switch (i) {
|
switch (i) {
|
||||||
case 0: pulseOverride(RELAY_A1); pulseOverride(RELAY_A3); break;
|
case 0: pulseOverride(RELAY_A1); pulseOverride(RELAY_A3); break;
|
||||||
@@ -216,36 +216,36 @@ static void rf_receiver_task(void* param) {
|
|||||||
vTaskDelete(NULL);
|
vTaskDelete(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
esp_err_t rf_init() {
|
esp_err_t rf_433_init() {
|
||||||
g_code_queue = xQueueCreate(5, sizeof(rf_code_t));
|
g_code_queue = xQueueCreate(5, sizeof(rf_code_t));
|
||||||
assert(g_code_queue);
|
assert(g_code_queue);
|
||||||
|
|
||||||
xTaskCreate(rf_receiver_task, TAG, 4096, NULL, 10, NULL);
|
xTaskCreate(rf_433_receiver_task, TAG, 4096, NULL, 10, NULL);
|
||||||
|
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
esp_err_t rf_stop() { return ESP_OK; }
|
esp_err_t rf_433_stop() { return ESP_OK; }
|
||||||
|
|
||||||
void rf_set_keycode(uint8_t index, int64_t code) {
|
void rf_433_set_keycode(uint8_t index, int64_t code) {
|
||||||
set_param(PARAM_KEYCODE_0+index, (param_value_t){.i64=code});
|
set_param_value_t(PARAM_KEYCODE_0+index, (param_value_t){.i64=code});
|
||||||
}
|
}
|
||||||
|
|
||||||
void rf_learn_keycode(uint8_t index) {
|
void rf_433_learn_keycode(uint8_t index) {
|
||||||
if (index >= 8) return;
|
if (index >= 8) return;
|
||||||
learn_flag = index;
|
learn_flag = index;
|
||||||
}
|
}
|
||||||
void rf_cancel_learn_keycode() {
|
void rf_433_cancel_learn_keycode() {
|
||||||
learn_flag = -1;
|
learn_flag = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int8_t rf_get_keycode() {
|
/*int8_t rf_433_get_keycode() {
|
||||||
rf_code_t received_code;
|
rf_code_t received_code;
|
||||||
|
|
||||||
if (xQueueReceive(g_code_queue, &received_code, 0) == pdPASS) {
|
if (xQueueReceive(g_code_queue, &received_code, 0) == pdPASS) {
|
||||||
int64_t newcode = ((int64_t)received_code.num_symbols << 56) | received_code.code;
|
int64_t newcode = ((int64_t)received_code.num_symbols << 56) | received_code.code;
|
||||||
|
|
||||||
for (uint8_t i = 0; i < NUM_RF_BUTTONS; i++) {
|
for (uint8_t i = 0; i < NUM_RF_BUTTONS; i++) {
|
||||||
if (newcode == get_param(PARAM_KEYCODE_0+i).i64)
|
if (newcode == get_param_value_t(PARAM_KEYCODE_0+i).i64)
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
ESP_LOGI("RF", "Received unknown code 0x%08lx (%d) [0x%16llx]", (unsigned long)received_code.code, received_code.num_symbols, (unsigned long long) newcode);
|
ESP_LOGI("RF", "Received unknown code 0x%08lx (%d) [0x%16llx]", (unsigned long)received_code.code, received_code.num_symbols, (unsigned long long) newcode);
|
||||||
@@ -253,7 +253,7 @@ int8_t rf_get_keycode() {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int64_t rf_get_raw_keycode() {
|
int64_t rf_433_get_raw_keycode() {
|
||||||
rf_code_t received_code;
|
rf_code_t received_code;
|
||||||
int64_t code = -1;
|
int64_t code = -1;
|
||||||
if (xQueueReceive(g_code_queue, &received_code, 0) == pdPASS) {
|
if (xQueueReceive(g_code_queue, &received_code, 0) == pdPASS) {
|
||||||
@@ -261,8 +261,8 @@ int64_t rf_get_raw_keycode() {
|
|||||||
//ESP_LOGI("RF", "Raw Code 0x%08lx (%d) [0x%16llx]", (unsigned long)received_code.code, received_code.num_symbols, (unsigned long long) code);
|
//ESP_LOGI("RF", "Raw Code 0x%08lx (%d) [0x%16llx]", (unsigned long)received_code.code, received_code.num_symbols, (unsigned long long) code);
|
||||||
}
|
}
|
||||||
return code;
|
return code;
|
||||||
}
|
}*/
|
||||||
|
|
||||||
void rf_clear_queue() {
|
void rf_433_clear_queue() {
|
||||||
xQueueReset(g_code_queue);
|
xQueueReset(g_code_queue);
|
||||||
}
|
}
|
||||||
30
main/rf_433.h
Normal file
30
main/rf_433.h
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
|
||||||
|
#ifndef RF_H
|
||||||
|
#define RF_H
|
||||||
|
|
||||||
|
#include <inttypes.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
|
||||||
|
#include "freertos/FreeRTOS.h"
|
||||||
|
#include "freertos/task.h"
|
||||||
|
#include "freertos/queue.h"
|
||||||
|
|
||||||
|
#define NUM_RF_BUTTONS 8
|
||||||
|
|
||||||
|
int64_t recieveKeycode();
|
||||||
|
|
||||||
|
esp_err_t rf_433_init();
|
||||||
|
esp_err_t rf_433_stop();
|
||||||
|
|
||||||
|
void rf_433_set_keycode(uint8_t index, int64_t code);
|
||||||
|
|
||||||
|
/*
|
||||||
|
int8_t rf_433_get_keycode();
|
||||||
|
int64_t rf_433_get_raw_keycode();
|
||||||
|
*/
|
||||||
|
|
||||||
|
void rf_433_learn_keycode(uint8_t index);
|
||||||
|
void rf_433_cancel_learn_keycode();
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -24,7 +24,6 @@
|
|||||||
#include "freertos/task.h"
|
#include "freertos/task.h"
|
||||||
#include "i2c.h"
|
#include "i2c.h"
|
||||||
#include "rtc_wdt.h"
|
#include "rtc_wdt.h"
|
||||||
#include "filemgmt.h"
|
|
||||||
|
|
||||||
//#include "esp32/rtc_clk.h" // For RTC_SLOW_FREQ_32K_XTAL enum and rtc_clk_slow_freq_set()
|
//#include "esp32/rtc_clk.h" // For RTC_SLOW_FREQ_32K_XTAL enum and rtc_clk_slow_freq_set()
|
||||||
#include "driver/rtc_io.h" // For RTC I/O handling (optional but recommended for pin configuration)
|
#include "driver/rtc_io.h" // For RTC I/O handling (optional but recommended for pin configuration)
|
||||||
@@ -85,7 +84,6 @@ void enter_deep_sleep(void)
|
|||||||
|
|
||||||
void rtc_set_time(struct tm *tm) {
|
void rtc_set_time(struct tm *tm) {
|
||||||
rtc_set = true;
|
rtc_set = true;
|
||||||
start_new_log_file();
|
|
||||||
struct timeval tv = { .tv_sec = mktime(tm), .tv_usec = 0 };
|
struct timeval tv = { .tv_sec = mktime(tm), .tv_usec = 0 };
|
||||||
settimeofday(&tv, NULL);
|
settimeofday(&tv, NULL);
|
||||||
reset_solar_fsm();
|
reset_solar_fsm();
|
||||||
|
|||||||
@@ -50,18 +50,18 @@ esp_err_t run_solar_fsm() {
|
|||||||
//if (rtc_is_set()) {
|
//if (rtc_is_set()) {
|
||||||
switch(current_charge_state) {
|
switch(current_charge_state) {
|
||||||
case CHG_STATE_BULK:
|
case CHG_STATE_BULK:
|
||||||
if (now > timer+get_param(PARAM_CHG_BULK_S).i64) {
|
if (now > timer+get_param_value_t(PARAM_CHG_BULK_S).i64) {
|
||||||
current_charge_state = CHG_STATE_FLOAT;
|
current_charge_state = CHG_STATE_FLOAT;
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case CHG_STATE_FLOAT:
|
case CHG_STATE_FLOAT:
|
||||||
// if we have sufficient voltage, reset the timer
|
// if we have sufficient voltage, reset the timer
|
||||||
if (vbat > get_param(PARAM_CHG_LOW_V).f32) {
|
if (vbat > get_param_value_t(PARAM_CHG_LOW_V).f32) {
|
||||||
timer = now;
|
timer = now;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (now > timer+get_param(PARAM_CHG_LOW_S).i64) {
|
if (now > timer+get_param_value_t(PARAM_CHG_LOW_S).i64) {
|
||||||
timer = now;
|
timer = now;
|
||||||
current_charge_state = CHG_STATE_BULK;
|
current_charge_state = CHG_STATE_BULK;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ static bool log_initialized = false;
|
|||||||
// PARAMETER FUNCTIONS
|
// PARAMETER FUNCTIONS
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
|
|
||||||
param_value_t get_param(param_idx_t id) {
|
param_value_t get_param_value_t(param_idx_t id) {
|
||||||
if (id >= NUM_PARAMS) {
|
if (id >= NUM_PARAMS) {
|
||||||
ESP_LOGE(TAG, "Invalid parameter ID: %d", id);
|
ESP_LOGE(TAG, "Invalid parameter ID: %d", id);
|
||||||
param_value_t err = {0};
|
param_value_t err = {0};
|
||||||
@@ -68,7 +68,7 @@ param_value_t get_param(param_idx_t id) {
|
|||||||
return parameter_table[id];
|
return parameter_table[id];
|
||||||
}
|
}
|
||||||
|
|
||||||
esp_err_t set_param(param_idx_t id, param_value_t val) {
|
esp_err_t set_param_value_t(param_idx_t id, param_value_t val) {
|
||||||
if (id >= NUM_PARAMS) {
|
if (id >= NUM_PARAMS) {
|
||||||
ESP_LOGE(TAG, "Invalid parameter ID: %d", id);
|
ESP_LOGE(TAG, "Invalid parameter ID: %d", id);
|
||||||
return ESP_ERR_INVALID_ARG;
|
return ESP_ERR_INVALID_ARG;
|
||||||
|
|||||||
@@ -122,8 +122,8 @@ extern const char* parameter_names[NUM_PARAMS];
|
|||||||
esp_err_t storage_init();
|
esp_err_t storage_init();
|
||||||
esp_err_t log_init();
|
esp_err_t log_init();
|
||||||
|
|
||||||
param_value_t get_param(param_idx_t id);
|
param_value_t get_param_value_t(param_idx_t id);
|
||||||
esp_err_t set_param(param_idx_t id, param_value_t val);
|
esp_err_t set_param_value_t(param_idx_t id, param_value_t val);
|
||||||
param_type_e get_param_type(param_idx_t id);
|
param_type_e get_param_type(param_idx_t id);
|
||||||
const char* get_param_name(param_idx_t id);
|
const char* get_param_name(param_idx_t id);
|
||||||
param_value_t get_param_default(param_idx_t id);
|
param_value_t get_param_default(param_idx_t id);
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
#include "storage.h"
|
#include "storage.h"
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include "rf.h"
|
#include "rf_433.h"
|
||||||
|
|
||||||
#define TAG "UART"
|
#define TAG "UART"
|
||||||
|
|
||||||
@@ -188,7 +188,7 @@ static void cmd_set_param(char *args) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
esp_err_t err = set_param(id, param_val);
|
esp_err_t err = set_param_value_t(id, param_val);
|
||||||
if (err == ESP_OK) {
|
if (err == ESP_OK) {
|
||||||
printf("OK: Parameter %u (%s) set to ",
|
printf("OK: Parameter %u (%s) set to ",
|
||||||
id, get_param_name(id));
|
id, get_param_name(id));
|
||||||
@@ -223,7 +223,7 @@ static void cmd_get_param(char *args) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Get parameter
|
// Get parameter
|
||||||
param_value_t val = get_param(id);
|
param_value_t val = get_param_value_t(id);
|
||||||
printf("Parameter %u (%s) = ", id, get_param_name(id));
|
printf("Parameter %u (%s) = ", id, get_param_name(id));
|
||||||
print_param_value(id, val);
|
print_param_value(id, val);
|
||||||
}
|
}
|
||||||
@@ -262,7 +262,7 @@ static void cmd_reset_param(char *args) {
|
|||||||
|
|
||||||
// Reset to default
|
// Reset to default
|
||||||
param_value_t default_val = get_param_default(id);
|
param_value_t default_val = get_param_default(id);
|
||||||
esp_err_t err = set_param(id, default_val);
|
esp_err_t err = set_param_value_t(id, default_val);
|
||||||
|
|
||||||
if (err == ESP_OK) {
|
if (err == ESP_OK) {
|
||||||
printf("OK: Parameter %u (%s) reset to default: ",
|
printf("OK: Parameter %u (%s) reset to default: ",
|
||||||
@@ -287,7 +287,7 @@ static void cmd_list_params(char *args) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
for (int i = 0; i < NUM_PARAMS; i++) {
|
for (int i = 0; i < NUM_PARAMS; i++) {
|
||||||
param_value_t val = get_param(i);
|
param_value_t val = get_param_value_t(i);
|
||||||
param_type_e type = get_param_type(i);
|
param_type_e type = get_param_type(i);
|
||||||
|
|
||||||
printf("%-3d | %-17s | %-4s | ", i, get_param_name(i), type_names[type]);
|
printf("%-3d | %-17s | %-4s | ", i, get_param_name(i), type_names[type]);
|
||||||
@@ -317,7 +317,7 @@ static void cmd_rf_learn(char *args) {
|
|||||||
char *id_str = strtok(args, " \t");
|
char *id_str = strtok(args, " \t");
|
||||||
|
|
||||||
if (id_str == NULL) {
|
if (id_str == NULL) {
|
||||||
rf_cancel_learn_keycode();
|
rf_433_cancel_learn_keycode();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -331,7 +331,7 @@ static void cmd_rf_learn(char *args) {
|
|||||||
param_idx_t id = (param_idx_t)id_u64;
|
param_idx_t id = (param_idx_t)id_u64;
|
||||||
if (id < 8) {
|
if (id < 8) {
|
||||||
printf("Listening for keycode for slot %d\n", id);
|
printf("Listening for keycode for slot %d\n", id);
|
||||||
rf_learn_keycode(id);
|
rf_433_learn_keycode(id);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
printf("ERROR: Keycode slot index out of bounds.\n");
|
printf("ERROR: Keycode slot index out of bounds.\n");
|
||||||
|
|||||||
3
main/webpage.h
Normal file
3
main/webpage.h
Normal file
File diff suppressed because one or more lines are too long
31
main/webpage_compile.py
Normal file
31
main/webpage_compile.py
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
import minify_html
|
||||||
|
import gzip
|
||||||
|
|
||||||
|
with open("landingpage.html", "r", encoding="utf-8") as fin:
|
||||||
|
original_html = fin.read()
|
||||||
|
|
||||||
|
minified_html = minify_html.minify(
|
||||||
|
original_html,
|
||||||
|
minify_js=True,
|
||||||
|
minify_css=True,
|
||||||
|
keep_comments=False, # Remove comments
|
||||||
|
keep_html_and_head_opening_tags=False, # Remove <html> and <head> if possible
|
||||||
|
keep_closing_tags=True, # Keep closing tags (safer; set False for more aggression if you test thoroughly)
|
||||||
|
remove_processing_instructions=True, # Remove <?xml ...> etc.
|
||||||
|
#keep_comments=False,
|
||||||
|
remove_bangs=False # Keep <!DOCTYPE> bang (removing saves bytes but can break some edge cases)
|
||||||
|
)
|
||||||
|
|
||||||
|
with open("webpage_minified.html", "w") as fout:
|
||||||
|
fout.write(minified_html)
|
||||||
|
|
||||||
|
|
||||||
|
minified_bytes = minified_html.encode('utf-8')
|
||||||
|
gzipped_bytes = gzip.compress(minified_bytes, compresslevel=9)
|
||||||
|
|
||||||
|
|
||||||
|
with open("webpage.h", "w") as fout:
|
||||||
|
fout.write("const char html_content[] = {")
|
||||||
|
fout.write(','.join(f'0x{byte:02x}' for byte in gzipped_bytes))
|
||||||
|
fout.write("};\n\n")
|
||||||
|
fout.write(f"const unsigned int html_content_len = {len(gzipped_bytes)};\n")
|
||||||
28
main/webpage_minified.html
Normal file
28
main/webpage_minified.html
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
<!doctype html><title>Control Panel</title><style>*{color:#eee;background-color:#111;font-family:sans-serif}input{text-align:right;box-sizing:border-box;background-color:#333;border:1px solid #666;width:100%;font-family:monospace}.changed{color:#111!important;background-color:#3d3!important}#commit_btn{color:#111;cursor:pointer;background-color:#3d3;border:none;width:100%;margin-top:10px;padding:10px;font-weight:700}#commit_btn[disabled]{color:#888;cursor:not-allowed;background-color:#444}table{border-collapse:collapse;width:100%}td{border-bottom:1px solid #222;padding:8px}tr:hover{background-color:#1a1a1a}</style></head><body><table id=table><tr><td>-</td><td>System Time</td><td><input id=in_time onchange=markChanged(this) step=1 type=datetime-local></td><td></td></tr><tr><td colspan=4><button disabled id=commit_btn onclick=commit_params()>Save Changes</button></td></tr></table><input accept=.bin id=firmware_file type=file><button id=upload_btn onclick=uploadFirmware()>Upload Firmware</button><script>let param_values=[];const param_names=[`Drive Distance`,`TPDF`,`Efuse Amt`,`Gain`,`Offset`],param_units=[`in`,`ft`,`in`,`V`,`ms`];function ge(x){return document.getElementById(x)}
|
||||||
|
// Highlight changed inputs and enable the save button
|
||||||
|
function markChanged(el){el.classList.add(`changed`),ge(`commit_btn`).disabled=!1}
|
||||||
|
// --- 1. GET DATA ---
|
||||||
|
function fetchStatus(){let xhr=new XMLHttpRequest;xhr.open(`GET`,`http://192.168.4.1/status`,!0),xhr.onload=function(){if(xhr.status===200)try{console.log(xhr.responseText);let data=JSON.parse(xhr.responseText);
|
||||||
|
// Update time field if available
|
||||||
|
if(data.time){let date=(/* @__PURE__ */ new Date(data.time*1e3)).toISOString().slice(0,19);ge(`in_time`).value=date}
|
||||||
|
// Store values (default to empty array if missing)
|
||||||
|
param_values=data.params||[]}catch(e){console.error(`Error parsing JSON`,e)}
|
||||||
|
// Always render table even if request fails or data is empty
|
||||||
|
renderTable()},xhr.onerror=function(e){console.error(`Network error`,e),renderTable()},xhr.send()}function renderTable(){let table=ge(`table`);
|
||||||
|
// Clear existing parameter rows (rows between index 0 and the last row)
|
||||||
|
for(;table.rows.length>2;)table.deleteRow(1);
|
||||||
|
// Loop through the NAMES array to ensure every input is shown
|
||||||
|
param_names.forEach((name,i)=>{let row=table.insertRow(table.rows.length-1);row.innerHTML=`
|
||||||
|
<td>${i}</td>
|
||||||
|
<td>${name}</td>
|
||||||
|
<td><input type="text" id="in_${i}" value="${param_values[i]!==void 0&¶m_values[i]!==null?param_values[i]:`null`}" oninput="markChanged(this)"></td>
|
||||||
|
<td>${param_units[i]||``}</td>
|
||||||
|
`})}
|
||||||
|
// --- 2. POST DATA ---
|
||||||
|
function commit_params(){ge(`commit_btn`).disabled=!0,document.querySelectorAll(`input.changed`).forEach(input=>{let xhr=new XMLHttpRequest;if(input.id===`in_time`){
|
||||||
|
// Time handling
|
||||||
|
let epoch=Math.floor(new Date(input.value).getTime()/1e3);xhr.open(`POST`,`http://192.168.4.1/st`,!0),xhr.setRequestHeader(`Content-Type`,`application/json`),xhr.send(JSON.stringify({time:epoch})),input.classList.remove(`changed`)}else{
|
||||||
|
// Parameter handling
|
||||||
|
let id=input.id.split(`_`)[1],val=input.value.toLowerCase()===`null`?null:parseFloat(input.value);xhr.open(`POST`,`/sp`,!0),xhr.setRequestHeader(`Content-Type`,`application/json`),xhr.onload=function(){xhr.status===200&&input.classList.remove(`changed`)},xhr.send(JSON.stringify({id:parseInt(id),value:val}))}})}function uploadFirmware(){let fileInput=ge(`firmware_file`);if(!fileInput.files.length){alert(`No file selected`);return}let file=fileInput.files[0],xhr=new XMLHttpRequest;xhr.open(`POST`,`http://192.168.4.1/ota`,!0),xhr.setRequestHeader(`Content-Type`,`application/octet-stream`),xhr.onload=function(){xhr.status===200?alert(`Upload successful. Device may reboot.`):alert(`Upload failed: `+xhr.status)},xhr.onerror=function(){alert(`Network error during upload`)},xhr.send(file)}
|
||||||
|
// Initial Load
|
||||||
|
window.onload=fetchStatus;</script></body></html>
|
||||||
333
main/webserver.c
Normal file
333
main/webserver.c
Normal file
@@ -0,0 +1,333 @@
|
|||||||
|
/* WiFi softAP Example
|
||||||
|
|
||||||
|
This example code is in the Public Domain (or CC0 licensed, at your option.)
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, this
|
||||||
|
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||||
|
CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "esp_ota_ops.h"
|
||||||
|
#include "esp_timer.h"
|
||||||
|
#include "rtc.h"
|
||||||
|
#include "string.h"
|
||||||
|
#include "freertos/FreeRTOS.h"
|
||||||
|
#include "freertos/task.h"
|
||||||
|
#include "esp_wifi.h"
|
||||||
|
#include "esp_system.h"
|
||||||
|
#include "esp_event.h"
|
||||||
|
#include "esp_log.h"
|
||||||
|
#include "nvs_flash.h"
|
||||||
|
#include "esp_http_server.h"
|
||||||
|
#include "esp_netif.h"
|
||||||
|
#include <math.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <sys/param.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include "stdio.h"
|
||||||
|
#include "storage.h"
|
||||||
|
//#include "mdns.h"
|
||||||
|
#include "webpage.h"
|
||||||
|
|
||||||
|
|
||||||
|
#define HOSTNAME "sc.local"
|
||||||
|
#define SOFT_AP_SSID "stockcropper"
|
||||||
|
#define SOFT_AP_PASSWORD "stockcropper"
|
||||||
|
#define SERVER_PORT 80
|
||||||
|
|
||||||
|
static const char *TAG = "WEBSERVER";
|
||||||
|
|
||||||
|
|
||||||
|
static httpd_handle_t httpServerInstance = NULL;
|
||||||
|
|
||||||
|
char httpBuffer[1024];
|
||||||
|
|
||||||
|
/* Handler to serve the HTML page */
|
||||||
|
static esp_err_t root_get_handler(httpd_req_t *req) {
|
||||||
|
ESP_LOGI(TAG, "root_get_handler");
|
||||||
|
// Send the HTML response
|
||||||
|
|
||||||
|
httpd_resp_set_type(req, "text/html"); // Original MIME type
|
||||||
|
httpd_resp_set_hdr(req, "Content-Encoding", "gzip"); // Tell browser it's gzipped
|
||||||
|
return httpd_resp_send(req, (const char *)html_content, html_content_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
static esp_err_t log_get_handler(httpd_req_t *req) {
|
||||||
|
ESP_LOGI(TAG, "log_get_handler");
|
||||||
|
// Send the HTML response
|
||||||
|
httpd_resp_set_type(req, "text/html");
|
||||||
|
return httpd_resp_send(req, html_content, HTTPD_RESP_USE_STRLEN);
|
||||||
|
}
|
||||||
|
|
||||||
|
// set time: timestamp (unix epoch, seconds)
|
||||||
|
static esp_err_t st_post_handler(httpd_req_t *req) {
|
||||||
|
ESP_LOGI(TAG, "st_post_handler");
|
||||||
|
// Send the HTML response
|
||||||
|
|
||||||
|
int ret=0;
|
||||||
|
int remaining = req -> content_len;
|
||||||
|
while (remaining > 0) {
|
||||||
|
if ((ret = httpd_req_recv(req, httpBuffer, MIN(remaining, sizeof(httpBuffer))))<= 0) {
|
||||||
|
if(ret == HTTPD_SOCK_ERR_TIMEOUT){
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
return ESP_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
ESP_LOGI(TAG, "ST POST %.*s", ret, httpBuffer);
|
||||||
|
return httpd_resp_send(req, "200 OK", HTTPD_RESP_USE_STRLEN);
|
||||||
|
}
|
||||||
|
|
||||||
|
// set parameters id & value
|
||||||
|
static esp_err_t sp_post_handler(httpd_req_t *req) {
|
||||||
|
ESP_LOGI(TAG, "sp_post_handler");
|
||||||
|
// Send the HTML response
|
||||||
|
httpd_resp_set_type(req, "text/html");
|
||||||
|
return httpd_resp_send(req, "/sp NOT IMPLEMENTED", HTTPD_RESP_USE_STRLEN);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static esp_err_t move_post_handler(httpd_req_t *req) {
|
||||||
|
ESP_LOGI(TAG, "move_post_handler");
|
||||||
|
// Send the HTML response
|
||||||
|
httpd_resp_set_type(req, "text/html");
|
||||||
|
return httpd_resp_send(req, "/move NOT IMPLEMENTED", HTTPD_RESP_USE_STRLEN);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static esp_err_t stop_post_handler(httpd_req_t *req) {
|
||||||
|
ESP_LOGI(TAG, "stop_post_handler");
|
||||||
|
// Send the HTML response
|
||||||
|
httpd_resp_set_type(req, "text/html");
|
||||||
|
return httpd_resp_send(req, "/stop NOT IMPLEMENTED", HTTPD_RESP_USE_STRLEN);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Handler for Status GET request*/
|
||||||
|
static esp_err_t status_get_handler(httpd_req_t *req) {
|
||||||
|
ESP_LOGI(TAG, "status_get_handler");
|
||||||
|
size_t head = 0;
|
||||||
|
|
||||||
|
// Set the response type to JSON
|
||||||
|
httpd_resp_set_type(req, "application/json");
|
||||||
|
|
||||||
|
// Start building the JSON string with time
|
||||||
|
head += sprintf(httpBuffer+head, "{\"time\":%lld,\"params\":[", system_rtc_get_raw_time());
|
||||||
|
|
||||||
|
for (param_idx_t i = 0; i < NUM_PARAMS; i++) {
|
||||||
|
if (i > 0) {
|
||||||
|
head += sprintf(httpBuffer+head, ",");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Retrieve the parameter; assuming get_param(i) returns a param_t struct with union
|
||||||
|
param_value_t param = get_param_value_t(i);
|
||||||
|
|
||||||
|
// Append the parameter value based on its type
|
||||||
|
switch (get_param_type(i)) {
|
||||||
|
case PARAM_TYPE_u8: head+=sprintf(httpBuffer+head, "%u", param.u8); break;
|
||||||
|
case PARAM_TYPE_i8: head+=sprintf(httpBuffer+head, "%d", param.i8); break;
|
||||||
|
case PARAM_TYPE_u16: head+=sprintf(httpBuffer+head, "%u", param.u16); break;
|
||||||
|
case PARAM_TYPE_i16: head+=sprintf(httpBuffer+head, "%d", param.i16); break;
|
||||||
|
case PARAM_TYPE_u32: head+=sprintf(httpBuffer+head, "%lu", (unsigned long)param.u32); break;
|
||||||
|
case PARAM_TYPE_i32: head+=sprintf(httpBuffer+head, "%ld", (long)param.i32); break;
|
||||||
|
case PARAM_TYPE_u64: head+=sprintf(httpBuffer+head, "%llu", param.u64); break;
|
||||||
|
case PARAM_TYPE_i64: head+=sprintf(httpBuffer+head, "%lld", param.i64); break;
|
||||||
|
case PARAM_TYPE_f32: head+=sprintf(httpBuffer+head, "%.8f", param.f32); break;
|
||||||
|
case PARAM_TYPE_f64: head+=sprintf(httpBuffer+head, "%.8f", param.f64); break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close the JSON array and object
|
||||||
|
head += sprintf(httpBuffer+head, "]}");
|
||||||
|
|
||||||
|
return httpd_resp_send(req, httpBuffer, head);
|
||||||
|
}
|
||||||
|
static esp_err_t ota_post_handler(httpd_req_t *req) {
|
||||||
|
ESP_LOGI(TAG, "OTA POST request received");
|
||||||
|
|
||||||
|
esp_ota_handle_t update_handle = 0;
|
||||||
|
const esp_partition_t *update_partition = esp_ota_get_next_update_partition(NULL);
|
||||||
|
if (update_partition == NULL) {
|
||||||
|
ESP_LOGE(TAG, "No OTA partition found");
|
||||||
|
return httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "No OTA partition");
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t err = esp_ota_begin(update_partition, OTA_SIZE_UNKNOWN, &update_handle);
|
||||||
|
if (err != ESP_OK) {
|
||||||
|
ESP_LOGE(TAG, "esp_ota_begin failed (%s)", esp_err_to_name(err));
|
||||||
|
return httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "OTA begin failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
char buf[1024];
|
||||||
|
int recv_len;
|
||||||
|
int total_len = req->content_len;
|
||||||
|
int remaining = total_len;
|
||||||
|
|
||||||
|
while (remaining > 0) {
|
||||||
|
recv_len = httpd_req_recv(req, buf, MIN(remaining, sizeof(buf)));
|
||||||
|
if (recv_len <= 0) {
|
||||||
|
if (recv_len == HTTPD_SOCK_ERR_TIMEOUT) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
esp_ota_abort(update_handle);
|
||||||
|
return httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "Receive failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
err = esp_ota_write(update_handle, (const void *)buf, recv_len);
|
||||||
|
if (err != ESP_OK) {
|
||||||
|
esp_ota_abort(update_handle);
|
||||||
|
ESP_LOGE(TAG, "esp_ota_write failed (%s)", esp_err_to_name(err));
|
||||||
|
return httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "OTA write failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
remaining -= recv_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = esp_ota_end(update_handle);
|
||||||
|
if (err != ESP_OK) {
|
||||||
|
ESP_LOGE(TAG, "esp_ota_end failed (%s)", esp_err_to_name(err));
|
||||||
|
return httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "OTA end failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
err = esp_ota_set_boot_partition(update_partition);
|
||||||
|
if (err != ESP_OK) {
|
||||||
|
ESP_LOGE(TAG, "esp_ota_set_boot_partition failed (%s)", esp_err_to_name(err));
|
||||||
|
return httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "Set boot partition failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
ESP_LOGI(TAG, "OTA update successful. Rebooting in 2 seconds...");
|
||||||
|
|
||||||
|
// Send response FIRST
|
||||||
|
httpd_resp_send(req, "OTA update successful, rebooting...", HTTPD_RESP_USE_STRLEN);
|
||||||
|
|
||||||
|
// THEN delay and reboot
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(2000)); // Give time for TCP to close properly
|
||||||
|
esp_restart();
|
||||||
|
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
httpd_uri_t uris[] = {{
|
||||||
|
.uri = "/status",
|
||||||
|
.method = HTTP_GET,
|
||||||
|
.handler = status_get_handler,
|
||||||
|
.user_ctx = NULL
|
||||||
|
},{
|
||||||
|
.uri = "/",
|
||||||
|
.method = HTTP_GET,
|
||||||
|
.handler = root_get_handler,
|
||||||
|
.user_ctx = NULL
|
||||||
|
},{
|
||||||
|
.uri = "/st",
|
||||||
|
.method = HTTP_ANY,
|
||||||
|
.handler = st_post_handler,
|
||||||
|
.user_ctx = NULL
|
||||||
|
},{
|
||||||
|
.uri = "/log",
|
||||||
|
.method = HTTP_GET,
|
||||||
|
.handler = log_get_handler,
|
||||||
|
.user_ctx = NULL
|
||||||
|
},{
|
||||||
|
.uri = "/sp",
|
||||||
|
.method = HTTP_POST,
|
||||||
|
.handler = sp_post_handler,
|
||||||
|
.user_ctx = NULL
|
||||||
|
},{
|
||||||
|
.uri = "/move",
|
||||||
|
.method = HTTP_POST,
|
||||||
|
.handler = move_post_handler,
|
||||||
|
.user_ctx = NULL
|
||||||
|
},{
|
||||||
|
.uri = "/stop",
|
||||||
|
.method = HTTP_POST,
|
||||||
|
.handler = stop_post_handler,
|
||||||
|
.user_ctx = NULL
|
||||||
|
},{
|
||||||
|
.uri = "/ota",
|
||||||
|
.method = HTTP_POST,
|
||||||
|
.handler = ota_post_handler,
|
||||||
|
.user_ctx = NULL
|
||||||
|
}};
|
||||||
|
|
||||||
|
|
||||||
|
static void startHttpServer(void) {
|
||||||
|
httpd_config_t config = HTTPD_DEFAULT_CONFIG();
|
||||||
|
config.server_port = SERVER_PORT;
|
||||||
|
|
||||||
|
ESP_LOGI(TAG, "Starting server on port: '%d'", config.server_port);
|
||||||
|
if (httpd_start(&httpServerInstance, &config) == ESP_OK) {
|
||||||
|
for (uint8_t i=0; i<(sizeof(uris)/sizeof(httpd_uri_t)); i++) {
|
||||||
|
httpd_register_uri_handler(httpServerInstance, &uris[i]);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Event handler for WiFi events */
|
||||||
|
static void wifi_event_handler(void* arg, esp_event_base_t event_base,
|
||||||
|
int32_t event_id, void* event_data) {
|
||||||
|
if (event_id == WIFI_EVENT_AP_STACONNECTED) {
|
||||||
|
ESP_LOGI(TAG, "Station connected.");
|
||||||
|
//startHttpServer();
|
||||||
|
} else if (event_id == WIFI_EVENT_AP_STADISCONNECTED) {
|
||||||
|
ESP_LOGI(TAG, "Station disconnected.");
|
||||||
|
//stopHttpServer();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void launchSoftAp() {
|
||||||
|
ESP_ERROR_CHECK(nvs_flash_init());
|
||||||
|
ESP_ERROR_CHECK(esp_netif_init());
|
||||||
|
ESP_ERROR_CHECK(esp_event_loop_create_default());
|
||||||
|
|
||||||
|
// Create default WiFi AP and get the netif handle
|
||||||
|
esp_netif_t *ap_netif = esp_netif_create_default_wifi_ap();
|
||||||
|
assert(ap_netif); // Optional: check for NULL
|
||||||
|
|
||||||
|
// Set your custom hostname here (max 32 chars, no spaces/special chars recommended)
|
||||||
|
ESP_ERROR_CHECK(esp_netif_set_hostname(ap_netif, HOSTNAME));
|
||||||
|
|
||||||
|
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
|
||||||
|
ESP_ERROR_CHECK(esp_wifi_init(&cfg));
|
||||||
|
|
||||||
|
// Register the event handler
|
||||||
|
ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT,
|
||||||
|
ESP_EVENT_ANY_ID,
|
||||||
|
&wifi_event_handler,
|
||||||
|
NULL,
|
||||||
|
NULL));
|
||||||
|
|
||||||
|
wifi_config_t wifi_config = {
|
||||||
|
.ap = {
|
||||||
|
.ssid = SOFT_AP_SSID,
|
||||||
|
.ssid_len = strlen(SOFT_AP_SSID),
|
||||||
|
.password = SOFT_AP_PASSWORD,
|
||||||
|
.max_connection = 4,
|
||||||
|
.authmode = WIFI_AUTH_WPA2_PSK
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_AP));
|
||||||
|
ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_AP, &wifi_config));
|
||||||
|
ESP_ERROR_CHECK(esp_wifi_start());
|
||||||
|
|
||||||
|
//dns_server_config_t dns_config = DNS_SERVER_CONFIG_SINGLE(HOSTNAME, "192.168.4.1");
|
||||||
|
//ESP_ERROR_CHECK(dns_server_start(&dns_config));
|
||||||
|
|
||||||
|
//ESP_ERROR_CHECK(mdns_init());
|
||||||
|
//ESP_ERROR_CHECK(mdns_hostname_set(HOSTNAME)); // Matches the netif hostname
|
||||||
|
//ESP_ERROR_CHECK(mdns_instance_name_set("My ESP32 Device")); // Optional friendly name
|
||||||
|
// After mdns_init() and hostname set
|
||||||
|
//ESP_ERROR_CHECK(mdns_service_add(NULL, "_http", "_tcp", 80, NULL, 0));
|
||||||
|
|
||||||
|
ESP_LOGI(TAG, "SoftAP set up. SSID:%s password:%s", SOFT_AP_SSID, SOFT_AP_PASSWORD);
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t webserver_init(void) {
|
||||||
|
launchSoftAp();
|
||||||
|
startHttpServer();
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
3
main/webserver.h
Normal file
3
main/webserver.h
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
#include "esp_err.h"
|
||||||
|
|
||||||
|
esp_err_t webserver_init(void);
|
||||||
16
sdkconfig
16
sdkconfig
@@ -353,14 +353,14 @@ CONFIG_ESPTOOLPY_FLASHFREQ_40M=y
|
|||||||
# CONFIG_ESPTOOLPY_FLASHFREQ_20M is not set
|
# CONFIG_ESPTOOLPY_FLASHFREQ_20M is not set
|
||||||
CONFIG_ESPTOOLPY_FLASHFREQ="40m"
|
CONFIG_ESPTOOLPY_FLASHFREQ="40m"
|
||||||
# CONFIG_ESPTOOLPY_FLASHSIZE_1MB is not set
|
# CONFIG_ESPTOOLPY_FLASHSIZE_1MB is not set
|
||||||
CONFIG_ESPTOOLPY_FLASHSIZE_2MB=y
|
# CONFIG_ESPTOOLPY_FLASHSIZE_2MB is not set
|
||||||
# CONFIG_ESPTOOLPY_FLASHSIZE_4MB is not set
|
# CONFIG_ESPTOOLPY_FLASHSIZE_4MB is not set
|
||||||
# CONFIG_ESPTOOLPY_FLASHSIZE_8MB is not set
|
CONFIG_ESPTOOLPY_FLASHSIZE_8MB=y
|
||||||
# CONFIG_ESPTOOLPY_FLASHSIZE_16MB is not set
|
# CONFIG_ESPTOOLPY_FLASHSIZE_16MB is not set
|
||||||
# CONFIG_ESPTOOLPY_FLASHSIZE_32MB is not set
|
# CONFIG_ESPTOOLPY_FLASHSIZE_32MB is not set
|
||||||
# CONFIG_ESPTOOLPY_FLASHSIZE_64MB is not set
|
# CONFIG_ESPTOOLPY_FLASHSIZE_64MB is not set
|
||||||
# CONFIG_ESPTOOLPY_FLASHSIZE_128MB is not set
|
# CONFIG_ESPTOOLPY_FLASHSIZE_128MB is not set
|
||||||
CONFIG_ESPTOOLPY_FLASHSIZE="2MB"
|
CONFIG_ESPTOOLPY_FLASHSIZE="8MB"
|
||||||
# CONFIG_ESPTOOLPY_HEADER_FLASHSIZE_UPDATE is not set
|
# CONFIG_ESPTOOLPY_HEADER_FLASHSIZE_UPDATE is not set
|
||||||
CONFIG_ESPTOOLPY_BEFORE_RESET=y
|
CONFIG_ESPTOOLPY_BEFORE_RESET=y
|
||||||
# CONFIG_ESPTOOLPY_BEFORE_NORESET is not set
|
# CONFIG_ESPTOOLPY_BEFORE_NORESET is not set
|
||||||
@@ -374,12 +374,12 @@ CONFIG_ESPTOOLPY_MONITOR_BAUD=115200
|
|||||||
#
|
#
|
||||||
# Partition Table
|
# Partition Table
|
||||||
#
|
#
|
||||||
CONFIG_PARTITION_TABLE_SINGLE_APP=y
|
# CONFIG_PARTITION_TABLE_SINGLE_APP is not set
|
||||||
# CONFIG_PARTITION_TABLE_SINGLE_APP_LARGE is not set
|
# CONFIG_PARTITION_TABLE_SINGLE_APP_LARGE is not set
|
||||||
# CONFIG_PARTITION_TABLE_TWO_OTA is not set
|
# CONFIG_PARTITION_TABLE_TWO_OTA is not set
|
||||||
# CONFIG_PARTITION_TABLE_CUSTOM is not set
|
CONFIG_PARTITION_TABLE_CUSTOM=y
|
||||||
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv"
|
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv"
|
||||||
CONFIG_PARTITION_TABLE_FILENAME="partitions_singleapp.csv"
|
CONFIG_PARTITION_TABLE_FILENAME="partitions.csv"
|
||||||
CONFIG_PARTITION_TABLE_OFFSET=0x8000
|
CONFIG_PARTITION_TABLE_OFFSET=0x8000
|
||||||
CONFIG_PARTITION_TABLE_MD5=y
|
CONFIG_PARTITION_TABLE_MD5=y
|
||||||
# end of Partition Table
|
# end of Partition Table
|
||||||
@@ -733,7 +733,7 @@ CONFIG_HTTPD_PURGE_BUF_LEN=32
|
|||||||
# ESP HTTPS OTA
|
# ESP HTTPS OTA
|
||||||
#
|
#
|
||||||
# CONFIG_ESP_HTTPS_OTA_DECRYPT_CB is not set
|
# CONFIG_ESP_HTTPS_OTA_DECRYPT_CB is not set
|
||||||
# CONFIG_ESP_HTTPS_OTA_ALLOW_HTTP is not set
|
CONFIG_ESP_HTTPS_OTA_ALLOW_HTTP=y
|
||||||
# end of ESP HTTPS OTA
|
# end of ESP HTTPS OTA
|
||||||
|
|
||||||
#
|
#
|
||||||
@@ -1880,7 +1880,7 @@ CONFIG_POST_EVENTS_FROM_ISR=y
|
|||||||
CONFIG_POST_EVENTS_FROM_IRAM_ISR=y
|
CONFIG_POST_EVENTS_FROM_IRAM_ISR=y
|
||||||
CONFIG_GDBSTUB_SUPPORT_TASKS=y
|
CONFIG_GDBSTUB_SUPPORT_TASKS=y
|
||||||
CONFIG_GDBSTUB_MAX_TASKS=32
|
CONFIG_GDBSTUB_MAX_TASKS=32
|
||||||
# CONFIG_OTA_ALLOW_HTTP is not set
|
CONFIG_OTA_ALLOW_HTTP=y
|
||||||
# CONFIG_TWO_UNIVERSAL_MAC_ADDRESS is not set
|
# CONFIG_TWO_UNIVERSAL_MAC_ADDRESS is not set
|
||||||
CONFIG_FOUR_UNIVERSAL_MAC_ADDRESS=y
|
CONFIG_FOUR_UNIVERSAL_MAC_ADDRESS=y
|
||||||
CONFIG_NUMBER_OF_UNIVERSAL_MAC_ADDRESS=4
|
CONFIG_NUMBER_OF_UNIVERSAL_MAC_ADDRESS=4
|
||||||
|
|||||||
@@ -353,14 +353,14 @@ CONFIG_ESPTOOLPY_FLASHFREQ_40M=y
|
|||||||
# CONFIG_ESPTOOLPY_FLASHFREQ_20M is not set
|
# CONFIG_ESPTOOLPY_FLASHFREQ_20M is not set
|
||||||
CONFIG_ESPTOOLPY_FLASHFREQ="40m"
|
CONFIG_ESPTOOLPY_FLASHFREQ="40m"
|
||||||
# CONFIG_ESPTOOLPY_FLASHSIZE_1MB is not set
|
# CONFIG_ESPTOOLPY_FLASHSIZE_1MB is not set
|
||||||
# CONFIG_ESPTOOLPY_FLASHSIZE_2MB is not set
|
CONFIG_ESPTOOLPY_FLASHSIZE_2MB=y
|
||||||
# CONFIG_ESPTOOLPY_FLASHSIZE_4MB is not set
|
# CONFIG_ESPTOOLPY_FLASHSIZE_4MB is not set
|
||||||
CONFIG_ESPTOOLPY_FLASHSIZE_8MB=y
|
# CONFIG_ESPTOOLPY_FLASHSIZE_8MB is not set
|
||||||
# CONFIG_ESPTOOLPY_FLASHSIZE_16MB is not set
|
# CONFIG_ESPTOOLPY_FLASHSIZE_16MB is not set
|
||||||
# CONFIG_ESPTOOLPY_FLASHSIZE_32MB is not set
|
# CONFIG_ESPTOOLPY_FLASHSIZE_32MB is not set
|
||||||
# CONFIG_ESPTOOLPY_FLASHSIZE_64MB is not set
|
# CONFIG_ESPTOOLPY_FLASHSIZE_64MB is not set
|
||||||
# CONFIG_ESPTOOLPY_FLASHSIZE_128MB is not set
|
# CONFIG_ESPTOOLPY_FLASHSIZE_128MB is not set
|
||||||
CONFIG_ESPTOOLPY_FLASHSIZE="8MB"
|
CONFIG_ESPTOOLPY_FLASHSIZE="2MB"
|
||||||
# CONFIG_ESPTOOLPY_HEADER_FLASHSIZE_UPDATE is not set
|
# CONFIG_ESPTOOLPY_HEADER_FLASHSIZE_UPDATE is not set
|
||||||
CONFIG_ESPTOOLPY_BEFORE_RESET=y
|
CONFIG_ESPTOOLPY_BEFORE_RESET=y
|
||||||
# CONFIG_ESPTOOLPY_BEFORE_NORESET is not set
|
# CONFIG_ESPTOOLPY_BEFORE_NORESET is not set
|
||||||
@@ -733,7 +733,7 @@ CONFIG_HTTPD_PURGE_BUF_LEN=32
|
|||||||
# ESP HTTPS OTA
|
# ESP HTTPS OTA
|
||||||
#
|
#
|
||||||
# CONFIG_ESP_HTTPS_OTA_DECRYPT_CB is not set
|
# CONFIG_ESP_HTTPS_OTA_DECRYPT_CB is not set
|
||||||
# CONFIG_ESP_HTTPS_OTA_ALLOW_HTTP is not set
|
CONFIG_ESP_HTTPS_OTA_ALLOW_HTTP=y
|
||||||
# end of ESP HTTPS OTA
|
# end of ESP HTTPS OTA
|
||||||
|
|
||||||
#
|
#
|
||||||
@@ -1880,7 +1880,7 @@ CONFIG_POST_EVENTS_FROM_ISR=y
|
|||||||
CONFIG_POST_EVENTS_FROM_IRAM_ISR=y
|
CONFIG_POST_EVENTS_FROM_IRAM_ISR=y
|
||||||
CONFIG_GDBSTUB_SUPPORT_TASKS=y
|
CONFIG_GDBSTUB_SUPPORT_TASKS=y
|
||||||
CONFIG_GDBSTUB_MAX_TASKS=32
|
CONFIG_GDBSTUB_MAX_TASKS=32
|
||||||
# CONFIG_OTA_ALLOW_HTTP is not set
|
CONFIG_OTA_ALLOW_HTTP=y
|
||||||
# CONFIG_TWO_UNIVERSAL_MAC_ADDRESS is not set
|
# CONFIG_TWO_UNIVERSAL_MAC_ADDRESS is not set
|
||||||
CONFIG_FOUR_UNIVERSAL_MAC_ADDRESS=y
|
CONFIG_FOUR_UNIVERSAL_MAC_ADDRESS=y
|
||||||
CONFIG_NUMBER_OF_UNIVERSAL_MAC_ADDRESS=4
|
CONFIG_NUMBER_OF_UNIVERSAL_MAC_ADDRESS=4
|
||||||
|
|||||||
Reference in New Issue
Block a user