LogLevel Fix and ramp range fix
This commit is contained in:
parent
660fa5f1c7
commit
3cf3c72f31
@ -58,10 +58,10 @@
|
||||
[
|
||||
{
|
||||
"en": true,
|
||||
"relay-index": 0,
|
||||
"relay-index": 1,
|
||||
"button-index": 0,
|
||||
"min": 1.0,
|
||||
"max": 100.0,
|
||||
"max": 90.0,
|
||||
"step": 1.5,
|
||||
"rate": 30.0,
|
||||
"skip-count": 5,
|
||||
@ -69,10 +69,10 @@
|
||||
},
|
||||
{
|
||||
"en": true,
|
||||
"relay-index": 1,
|
||||
"relay-index": 2,
|
||||
"button-index": 1,
|
||||
"min": 1.0,
|
||||
"max": 100.0,
|
||||
"max": 90.0,
|
||||
"step": 1.5,
|
||||
"rate": 30.0,
|
||||
"skip-count": 5,
|
||||
@ -134,9 +134,24 @@
|
||||
"tx433": {
|
||||
"en": "true"
|
||||
},
|
||||
"ble":{
|
||||
"en": true,
|
||||
"name": "Ata_Lights",
|
||||
"core": 1
|
||||
"fire-animation": {
|
||||
"speed": 60,
|
||||
"cooling": 66,
|
||||
"sparking": 62,
|
||||
"brightness": 240
|
||||
},
|
||||
"comets-animation": {
|
||||
"speed": 80,
|
||||
"size-factor": 0.2,
|
||||
"count": 3,
|
||||
"cycles": 2,
|
||||
"min-fade": 16,
|
||||
"max-fade": 192
|
||||
},
|
||||
"snakes-animation": {
|
||||
"speed": 80,
|
||||
"cycles": 2,
|
||||
"multiplier": 6
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -130,10 +130,5 @@
|
||||
},
|
||||
"tx433": {
|
||||
"en": "true"
|
||||
},
|
||||
"ble":{
|
||||
"en": true,
|
||||
"name": "Ata_Lights",
|
||||
"core": 1
|
||||
}
|
||||
}
|
||||
|
||||
@ -60,7 +60,7 @@
|
||||
"relay-index": 0,
|
||||
"button-index": 0,
|
||||
"min": 1.0,
|
||||
"max": 100.0,
|
||||
"max": 90.0,
|
||||
"step": 1.5,
|
||||
"rate": 30.0,
|
||||
"skip-count": 5,
|
||||
@ -71,7 +71,7 @@
|
||||
"relay-index": 1,
|
||||
"button-index": 1,
|
||||
"min": 1.0,
|
||||
"max": 100.0,
|
||||
"max": 90.0,
|
||||
"step": 1.5,
|
||||
"rate": 30.0,
|
||||
"skip-count": 5,
|
||||
@ -132,10 +132,5 @@
|
||||
},
|
||||
"tx433": {
|
||||
"en": "true"
|
||||
},
|
||||
"ble":{
|
||||
"en": true,
|
||||
"name": "Ata_Lights",
|
||||
"core": 1
|
||||
}
|
||||
}
|
||||
|
||||
@ -135,10 +135,5 @@
|
||||
},
|
||||
"tx433": {
|
||||
"en": "true"
|
||||
},
|
||||
"ble":{
|
||||
"en": true,
|
||||
"name": "Ata_Lights",
|
||||
"core": 1
|
||||
}
|
||||
}
|
||||
|
||||
@ -129,10 +129,5 @@
|
||||
},
|
||||
"tx433": {
|
||||
"en": "true"
|
||||
},
|
||||
"ble":{
|
||||
"en": true,
|
||||
"name": "Ata_Lights",
|
||||
"core": 1
|
||||
}
|
||||
}
|
||||
|
||||
@ -130,10 +130,5 @@
|
||||
},
|
||||
"tx433": {
|
||||
"en": "true"
|
||||
},
|
||||
"ble":{
|
||||
"en": true,
|
||||
"name": "Ata_Lights",
|
||||
"core": 1
|
||||
}
|
||||
}
|
||||
|
||||
@ -61,7 +61,7 @@
|
||||
"relay-index": 0,
|
||||
"button-index": 0,
|
||||
"min": 1.0,
|
||||
"max": 100.0,
|
||||
"max": 90.0,
|
||||
"step": 1.5,
|
||||
"rate": 30.0,
|
||||
"skip-count": 5,
|
||||
@ -72,7 +72,7 @@
|
||||
"relay-index": 1,
|
||||
"button-index": 1,
|
||||
"min": 1.0,
|
||||
"max": 100.0,
|
||||
"max": 90.0,
|
||||
"step": 1.5,
|
||||
"rate": 30.0,
|
||||
"skip-count": 5,
|
||||
@ -131,10 +131,5 @@
|
||||
},
|
||||
"tx433": {
|
||||
"en": "true"
|
||||
},
|
||||
"ble":{
|
||||
"en": true,
|
||||
"name": "Ata_Lights",
|
||||
"core": 1
|
||||
}
|
||||
}
|
||||
|
||||
@ -130,10 +130,5 @@
|
||||
},
|
||||
"tx433": {
|
||||
"en": "true"
|
||||
},
|
||||
"ble":{
|
||||
"en": true,
|
||||
"name": "Ata_Lights",
|
||||
"core": 1
|
||||
}
|
||||
}
|
||||
|
||||
@ -130,10 +130,5 @@
|
||||
},
|
||||
"tx433": {
|
||||
"en": "true"
|
||||
},
|
||||
"ble":{
|
||||
"en": true,
|
||||
"name": "Ata_Lights",
|
||||
"core": 1
|
||||
}
|
||||
}
|
||||
|
||||
@ -131,11 +131,6 @@
|
||||
},
|
||||
"tx433": {
|
||||
"en": "true"
|
||||
},
|
||||
"ble":{
|
||||
"en": true,
|
||||
"name": "FlashStik",
|
||||
"core": 1
|
||||
}
|
||||
}
|
||||
|
||||
@ -129,10 +129,5 @@
|
||||
},
|
||||
"tx433": {
|
||||
"en": false
|
||||
},
|
||||
"ble":{
|
||||
"en": true,
|
||||
"name": "Ata_Lights",
|
||||
"core": 1
|
||||
}
|
||||
}
|
||||
|
||||
@ -131,25 +131,6 @@
|
||||
"tx433": {
|
||||
"en": "true"
|
||||
},
|
||||
"ble":{
|
||||
"en": true,
|
||||
"name": "Ata_Lights",
|
||||
"core": 1
|
||||
},
|
||||
"wifi-client":{
|
||||
"en": true,
|
||||
"mdns-name": "atadev",
|
||||
"ssid": "padillaguest",
|
||||
"pass": "padillaguest"
|
||||
},
|
||||
"wifi-ap":{
|
||||
"ssid": "ATA_AP",
|
||||
"append-id": true,
|
||||
"pass": "12345678",
|
||||
"ip": [192,168,10.1],
|
||||
"gateway": [192,168,10,200],
|
||||
"subnet": [255,255,255,0]
|
||||
},
|
||||
"animation1":{
|
||||
"white-max-time": 30,
|
||||
"white-min": 20,
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
<title>Edit file</title>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link href="/css/global-style.css" rel="stylesheet">
|
||||
<!--<link href="/css/global-style.css" rel="stylesheet">-->
|
||||
<link href="/css/nav.css" rel="stylesheet">
|
||||
|
||||
<style>
|
||||
@ -168,7 +168,7 @@
|
||||
|
||||
<!-- Stretchy editor space -->
|
||||
<div class="editor-area">
|
||||
<textarea name="edit-textarea" id="edit-textarea" wrap="off" placeholder="File contents will appear here..."></textarea>
|
||||
<textarea name="edit-textarea" id="edit-textarea" wrap="off" placeholder="File contents is empty..."></textarea>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
@ -5,7 +5,7 @@
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link href="/css/global-style.css" rel="stylesheet">
|
||||
<link href="/css/nav.css" rel="stylesheet">
|
||||
<link href="css/nav.css" rel="stylesheet">
|
||||
|
||||
<style>
|
||||
#file-row:nth-child(odd) {
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
<title>File Manager</title>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link href="/css/global-style.css" rel="stylesheet">
|
||||
<!--<link href="/css/global-style.css" rel="stylesheet">-->
|
||||
<link href="/css/nav.css" rel="stylesheet">
|
||||
|
||||
<style>
|
||||
@ -66,6 +66,7 @@
|
||||
"cinttypes": "cpp",
|
||||
"typeinfo": "cpp"
|
||||
},
|
||||
"liveServer.settings.multiRootWorkspaceName": "esp32s3_atabooth_8mb"
|
||||
"liveServer.settings.multiRootWorkspaceName": "esp32s3_atabooth_8mb",
|
||||
"liveServer.settings.port": 5501
|
||||
}
|
||||
}
|
||||
@ -16,8 +16,38 @@
|
||||
|
||||
#define CYCLES_PER_DIRECTION 2
|
||||
|
||||
void Animation_Init(void);
|
||||
#define FIRE_COOLING 55
|
||||
#define FIRE_SPARKING 120
|
||||
#define FIRE_brightness 240
|
||||
|
||||
struct ANIM_FIRE {
|
||||
int speed;
|
||||
uint8_t cooling = FIRE_COOLING; // How much does the fire cool as it rises. Less cooling = taller flames. Default 55, suggested range 20-100
|
||||
uint8_t sparking = FIRE_SPARKING; // What chance (out of 255) is there that a new spark will be lit. Higher chance = more roaring fire. Default 120, suggested range 50-200
|
||||
uint8_t brightness = FIRE_brightness; // Overall brightness of the fire effect. Default 240, suggested range 50-255
|
||||
};
|
||||
extern ANIM_FIRE fireSettings;
|
||||
|
||||
struct ANIM_COMET {
|
||||
int speed;
|
||||
int minFade;
|
||||
int maxFade;
|
||||
float sizeFactor;
|
||||
int cycles;
|
||||
int count;
|
||||
};
|
||||
extern ANIM_COMET cometSettings;
|
||||
|
||||
struct ANIM_SNAKES{
|
||||
int speed;
|
||||
int cycles;
|
||||
int multiplier;
|
||||
};
|
||||
extern ANIM_SNAKES snakeSettings;
|
||||
|
||||
|
||||
|
||||
void Animation_Init(void);
|
||||
void Animation_Loop(bool volatile& loop_active_flag, int speed, std::function<int()> callback);
|
||||
void Animation_Loop_Limited(bool volatile& loop_active_flag, int speed, TickType_t duration, std::function<int()> callback);
|
||||
void Animation_Loop_Cycles(bool volatile& loop_active_flag, int speed, uint32_t loop_cycles, std::function<int()> callback);
|
||||
@ -36,7 +66,7 @@ void Anim_Comets(bool volatile& activeFlag, CRGB* leds, int size, const COLOR_PA
|
||||
//void Anim_Comet_Rainbow(bool volatile& activeFlag, CRGB* leds, int size, int speed);
|
||||
|
||||
void Anim_TimedFill(bool volatile& activeFlag, CRGB* leds, int size, CRGB col1, CRGB col2, int totalDurationMs, int shift);
|
||||
void Anim_TimedFill_Flash(bool volatile& activeFlag, CRGB* leds, int size, PWM_Output* pwmOut, PWM_OUT_SETTINGS* pwmSettings, int pwmOutDelay, int flashTimeout, CRGB baseCol, CRGB fillCol, int totalDurationMs, int shift = 0);
|
||||
void Anim_TimedFill_Flash(bool volatile& activeFlag, CRGB* leds, int size, PWM_Output* pwmOut, RAMP_LIGHT_SETTINGS* pwmSettings, int pwmOutDelay, int flashTimeout, CRGB baseCol, CRGB fillCol, int totalDurationMs, int shift = 0);
|
||||
|
||||
void Anim_ColorBreath(bool volatile& activeFlag, CRGB* leds, int size, const COLOR_PACK& colors, uint32_t timeMs, int speed);
|
||||
|
||||
|
||||
@ -17,6 +17,7 @@ board_build.partitions = partitions_8mb_ota_2mb_ee.cvs
|
||||
monitor_speed = 115200
|
||||
monitor_filters = esp32_exception_decoder
|
||||
board_build.sdkconfig_defaults = sdkconfig.defaults
|
||||
|
||||
lib_deps =
|
||||
bblanchon/ArduinoJson
|
||||
makuna/NeoPixelBus @ ^2.8.3
|
||||
@ -33,8 +34,9 @@ lib_deps =
|
||||
build_flags =
|
||||
-mfix-esp32-psram-cache-issue
|
||||
-D CONFIG_LOG_DYNAMIC_LEVEL_CONTROL=1
|
||||
#-D CORE_DEBUG_LEVEL=ARDUHAL_LOG_LEVEL_VERBOSE
|
||||
-D LOG_LOCAL_LEVEL=5
|
||||
-D CORE_DEBUG_LEVEL=ARDUHAL_LOG_LEVEL_INFO
|
||||
#-D CORE_DEBUG_LEVEL=ARDUHAL_LOG_LEVEL_INFO
|
||||
-D CONFIG_ARDUHAL_LOG_COLORS=1
|
||||
#-Os
|
||||
#-ffunction-sections
|
||||
|
||||
@ -25,7 +25,10 @@ TaskHandle_t Ramp_Front_Light_Task_Handle;
|
||||
LEDSTRIP_SETTINGS ledSettings[2];
|
||||
volatile bool AnimationLooping = false;
|
||||
ANIM_EVENT prevAnimEvent = {0};
|
||||
QueueHandle_t animationQueue = xQueueCreate( 4, sizeof( ANIM_EVENT ) );
|
||||
//QueueHandle_t animationQueue = xQueueCreate( 4, sizeof( ANIM_EVENT ) );
|
||||
|
||||
static QueueHandle_t animationQueue = NULL;
|
||||
static SemaphoreHandle_t fastledMutex = NULL;
|
||||
|
||||
bool upgradeMode = false;
|
||||
|
||||
@ -36,7 +39,6 @@ bool upgradeMode = false;
|
||||
//bool fillAnimationActive = false;
|
||||
|
||||
void RGB_Lights_Set_Animation(int animIndex, uint8_t red, uint8_t grn, uint8_t blu){
|
||||
|
||||
// Trigger to exit curring looping animation
|
||||
if(AnimationLooping){
|
||||
AnimationLooping = false;
|
||||
@ -72,6 +74,21 @@ void Lights_Set_White(uint8_t val){
|
||||
|
||||
|
||||
void Init_RGB_Lights_Task(bool upgrade){
|
||||
// create queue & mutex here and check
|
||||
if (animationQueue == NULL) {
|
||||
animationQueue = xQueueCreate(4, sizeof(ANIM_EVENT));
|
||||
if (animationQueue == NULL) {
|
||||
ESP_LOGE(tag, "Failed to create animationQueue");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// validate ledSettings[] fields before allocating
|
||||
if (ledSettings[0].size <= 0) {
|
||||
ESP_LOGE(tag, "Invalid ledSettings[0].size");
|
||||
return;
|
||||
}
|
||||
|
||||
upgradeMode = upgrade;
|
||||
ledSettings[0].leds = new CRGB[ledSettings[0].size];
|
||||
Init_RGB_Strip(ledSettings[0].leds, ledSettings[0].pin, ledSettings[0].size, ledSettings[0].rgbOrder, ledSettings[0].chip, ledSettings[0].bright);
|
||||
@ -87,131 +104,6 @@ void Init_RGB_Lights_Task(bool upgrade){
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
void Init_Ramp_Front_Light_Task(void){
|
||||
// Check if pwmOutputs[0] is available before creating the task
|
||||
if(pwmOutputs[0] == nullptr) {
|
||||
ESP_LOGE(tag, "Cannot create Ramp Front Light Task: pwmOutputs[0] is not initialized");
|
||||
return;
|
||||
}
|
||||
|
||||
// Create task with moderate stack size - 2KB should be sufficient
|
||||
BaseType_t result = xTaskCreatePinnedToCore(Ramp_Front_Light_Control_Task, "Ramp_Front_Light_Task", 1024*2, NULL, 1, &Ramp_Front_Light_Task_Handle, (FASTLED_CORE ? 1 : 0));
|
||||
|
||||
if(result != pdPASS) {
|
||||
ESP_LOGE(tag, "Failed to create Ramp Front Light Task, error: %d", result);
|
||||
Ramp_Front_Light_Task_Handle = NULL;
|
||||
} else {
|
||||
ESP_LOGI(tag, "Ramp Front Light Task Created...");
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
#define RAMP_INTERVAL 25
|
||||
#define FRONTLIGHT_TIMEOUT 20000
|
||||
int startDelay = 0;
|
||||
int rampTime = 0;
|
||||
bool rampRestart = false;
|
||||
float FrontLightMin = 0.0;
|
||||
|
||||
void Ramp_Front_Light_Control_Task(void *parameters)
|
||||
{
|
||||
float currPwmValue = 0.0;
|
||||
float outValue = 0.0;
|
||||
int timeCounter = 0;
|
||||
|
||||
while(1) {
|
||||
|
||||
if(rampRestart == false){
|
||||
vTaskSuspend(NULL); // Wait to be triggered
|
||||
}
|
||||
rampRestart = false; // Clear the flag immediately
|
||||
|
||||
// Safety check: Ensure pwmOutputs[0] is initialized
|
||||
if(pwmOutputs[0] == nullptr) {
|
||||
ESP_LOGE(tag, "pwmOutputs[0] is null, cannot control front light");
|
||||
rampRestart = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Wait for start delay to finish
|
||||
while(!rampRestart && fillAnimationActive && startDelay > 0){
|
||||
vTaskDelay(10 / portTICK_PERIOD_MS);
|
||||
startDelay -= 10;
|
||||
}
|
||||
|
||||
if(rampRestart){
|
||||
continue; // Restart if requested during delay
|
||||
}
|
||||
|
||||
//currPwmValue = pwmOutputs[0]->getDuty(); // Get current PWM value
|
||||
currPwmValue = FrontLightMin; // Always start from min value
|
||||
pwmOutputs[0]->setOutput(currPwmValue); // Ensure starting point is set
|
||||
|
||||
// Ramp Up the Front Light linearly
|
||||
timeCounter = 0; // Reset timer for ramp up
|
||||
int rampMs = rampTime;
|
||||
while(!rampRestart && fillAnimationActive && rampMs > 0){
|
||||
timeCounter += RAMP_INTERVAL;
|
||||
outValue = map(timeCounter, 0, rampTime, currPwmValue, 100);
|
||||
pwmOutputs[0]->setOutput(outValue);
|
||||
vTaskDelay(RAMP_INTERVAL / portTICK_PERIOD_MS);
|
||||
rampMs -= RAMP_INTERVAL;
|
||||
}
|
||||
|
||||
if(rampRestart){
|
||||
continue; // Restart the ramp up if requested
|
||||
}
|
||||
|
||||
// Max Wait fill animation to end or timeout
|
||||
int frontLightTimeout = FRONTLIGHT_TIMEOUT;
|
||||
while(!rampRestart && fillAnimationActive && frontLightTimeout > 0){
|
||||
vTaskDelay(10 / portTICK_PERIOD_MS);
|
||||
frontLightTimeout -= 10;
|
||||
}
|
||||
|
||||
if(rampRestart){
|
||||
pwmOutputs[0]->setOutput(0); // Ensure it's fully off
|
||||
continue; // Restart the ramp up if requested
|
||||
}
|
||||
|
||||
// Ramp Down the Front Light linearly
|
||||
timeCounter = 0; // Reset timer for ramp down
|
||||
rampMs = rampTime;
|
||||
while(!rampRestart && fillAnimationActive && rampMs > 0){
|
||||
timeCounter += RAMP_INTERVAL;
|
||||
outValue = map(timeCounter, 0, rampTime, 100 , currPwmValue);
|
||||
pwmOutputs[0]->setOutput(outValue);
|
||||
vTaskDelay(RAMP_INTERVAL / portTICK_PERIOD_MS);
|
||||
rampMs -= RAMP_INTERVAL;
|
||||
}
|
||||
|
||||
// Cycle completed - ensure clean final state
|
||||
if(!rampRestart){
|
||||
pwmOutputs[0]->setOutput(FrontLightMin); // Ensure final state is minimum
|
||||
fillAnimationActive = false; // Clear animation flag
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Start_RampUp_Front_Light(int _rampTime, int _startDelay)
|
||||
{
|
||||
// Check if the task exists before trying to control it
|
||||
if(Ramp_Front_Light_Task_Handle == NULL) {
|
||||
ESP_LOGW(tag, "Cannot start front light ramp: task not created");
|
||||
return;
|
||||
}
|
||||
|
||||
rampTime = _rampTime;
|
||||
startDelay = _startDelay;
|
||||
fillAnimationActive = true;
|
||||
rampRestart = true;
|
||||
vTaskResume(Ramp_Front_Light_Task_Handle);
|
||||
}
|
||||
*/
|
||||
|
||||
void Animation_Loop_Exit(void){
|
||||
if( Animation_Task_Handle ){
|
||||
xTaskNotifyGive( Animation_Task_Handle );
|
||||
@ -509,11 +401,11 @@ void RGB_Lights_Control_Task(void *parameters){
|
||||
ESP_LOGD(tag, "New Animation Event: Index: %d", AnimEvent.AnimationIndex);
|
||||
switch (AnimEvent.AnimationIndex) {
|
||||
|
||||
case -3: // Set Shift
|
||||
case -3:{ // Set Shift
|
||||
if (AnimEvent.data.data[0] >= 0 && AnimEvent.data.data[0] < ledSettings[0].size) {
|
||||
fill_solid(ledSettings[0].leds, ledSettings[0].size, CRGB::Black);
|
||||
ledSettings[0].shift = AnimEvent.data.data[0];
|
||||
vTaskDelay(25 / portTICK_PERIOD_MS);
|
||||
vTaskDelay(pdMS_TO_TICKS(25));
|
||||
setPixel1(ledSettings[0], 0, CRGB::White * FastLED.getBrightness() / 255);
|
||||
FastLED.show();
|
||||
ESP_LOGD(tag, "Set Shift: %d", ledSettings[0].shift);
|
||||
@ -521,37 +413,54 @@ void RGB_Lights_Control_Task(void *parameters){
|
||||
ESP_LOGW(tag, "Pixel index out of range: %d", AnimEvent.data.data[0]);
|
||||
}
|
||||
break;
|
||||
case -2: // Fill Static Color
|
||||
}
|
||||
case -2:{ // Fill Static Color
|
||||
fill_solid(ledSettings[0].leds, ledSettings[0].size, CRGB(AnimEvent.data.red, AnimEvent.data.grn, AnimEvent.data.blu));
|
||||
FastLED.show();
|
||||
ESP_LOGD(tag, "Static Color");
|
||||
break;
|
||||
case -1:
|
||||
}
|
||||
case -1:{
|
||||
FastLED.clear();
|
||||
FastLED.show();
|
||||
ESP_LOGD(tag, "LEDs Off");
|
||||
break;
|
||||
case 0:
|
||||
}
|
||||
case 0:{
|
||||
fill_solid(ledSettings[0].leds, ledSettings[0].size, CRGB::Black);
|
||||
FastLED.show();
|
||||
break;
|
||||
}
|
||||
case 1 ... 5: { // Timed Fill Animations
|
||||
int timeDuration = AnimEvent.AnimationIndex * 1000 - 400;
|
||||
int whiteDelay = timeDuration - 1000;
|
||||
if (whiteDelay < 800) whiteDelay = 800; // minimum 8 seconds
|
||||
Anim_TimedFill_Flash(AnimationLooping, ledSettings[0].leds, ledSettings[0].size, pwmOutputs[0], &sys_settings.pwmOutSettings[0], whiteDelay, 20000, CRGB::Black, CRGB::White, timeDuration, ledSettings[0].shift);
|
||||
float tempMax = -1;
|
||||
if(AnimEvent.AnimationIndex == 1 && sys_settings.rampLightSettings[0].max > 70.0) {
|
||||
tempMax = sys_settings.rampLightSettings[0].max; // preserve user setting if higher than 70
|
||||
sys_settings.rampLightSettings[0].max = 70.0;
|
||||
}
|
||||
int timeDuration = (AnimEvent.AnimationIndex * 1000) - 100;
|
||||
int whiteDelay = timeDuration - 1000;
|
||||
if (whiteDelay < 0) whiteDelay = 0;
|
||||
Anim_TimedFill_Flash(AnimationLooping, ledSettings[0].leds, ledSettings[0].size, pwmOutputs[sys_settings.rampLightSettings[0].pwmOutIndex], &sys_settings.rampLightSettings[0], whiteDelay, 20000, CRGB::Black, CRGB(CRGB::White).nscale8(180), timeDuration, ledSettings[0].shift);
|
||||
|
||||
// restore ramp light max if it was changed
|
||||
if(tempMax > 0){
|
||||
sys_settings.rampLightSettings[0].max = tempMax; // restore user setting
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 6:
|
||||
case 6:{
|
||||
// RGB White and Dedicated White all on with timeout and brightness reduction
|
||||
Anim_SolidWhite(AnimationLooping, ledSettings[0].leds, pwmOutputs[0], ledSettings[0].size, 240, 30000);
|
||||
Anim_SolidWhite(AnimationLooping, ledSettings[0].leds, pwmOutputs[sys_settings.rampLightSettings[0].pwmOutIndex], ledSettings[0].size, 240, 30000);
|
||||
break;
|
||||
case 7:
|
||||
}
|
||||
case 7:{
|
||||
Anim_Rainbow(AnimationLooping, ledSettings[0].leds, ledSettings[0].size, 60);
|
||||
break;
|
||||
case 8 ... 12:
|
||||
}
|
||||
case 8 ... 12:{
|
||||
Anim_GradientRotate(AnimationLooping, ledSettings[0].leds, ledSettings[0].size, gradient_colorPack[AnimEvent.AnimationIndex - 8], 80);
|
||||
break;
|
||||
}
|
||||
case 13 ... 17: { // Fire Animations
|
||||
COLOR_PACK fp = fireColorPacks[AnimEvent.AnimationIndex - 13]; // copy const pack to mutable
|
||||
CRGBPalette16 firePalette;
|
||||
@ -559,71 +468,90 @@ void RGB_Lights_Control_Task(void *parameters){
|
||||
Anim_Fire(AnimationLooping, ledSettings[0].leds, ledSettings[0].size, 60, firePalette, ledSettings[0].shift);
|
||||
break;
|
||||
}
|
||||
case 18 ... 20: // Sparkle/Twinkle
|
||||
case 18 ... 20:{ // Sparkle/Twinkle
|
||||
Anim_Sparkle(AnimationLooping, ledSettings[0].leds, ledSettings[0].size, tripple_colorPacks[0], 40, 20);
|
||||
break;
|
||||
case 21:
|
||||
}
|
||||
case 21: {
|
||||
Anim_ColorBreath(AnimationLooping, ledSettings[0].leds, ledSettings[0].size, colorPack_RAINBOW, 7000, 90);
|
||||
break;
|
||||
case 22: // Rain Animation
|
||||
}
|
||||
case 22:{ // Rain Animation
|
||||
Anim_Morph(AnimationLooping, ledSettings[0].leds, ledSettings[0].size, colorPack_RAINBOW, 20, 40);
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
// Comets
|
||||
case 23:
|
||||
case 23: {
|
||||
Anim_Comets(AnimationLooping, ledSettings[0].leds, ledSettings[0].size, colorPack_RAINBOW, 40, 85, RANDOM_DECAY, 1);
|
||||
break;
|
||||
case 24 ... 31:
|
||||
}
|
||||
case 24 ... 31:{
|
||||
Anim_Comets(AnimationLooping, ledSettings[0].leds, ledSettings[0].size, single_colorPacks[AnimEvent.AnimationIndex - 24], 40, 85, RANDOM_DECAY, 6);
|
||||
break;
|
||||
case 32 ... 40:
|
||||
}
|
||||
case 32 ... 40:{
|
||||
Anim_Comets(AnimationLooping, ledSettings[0].leds, ledSettings[0].size, double_colorPacks[AnimEvent.AnimationIndex - 32], 40, 85, RANDOM_DECAY, 3);
|
||||
break;
|
||||
case 41 ... 49:
|
||||
}
|
||||
case 41 ... 49:{
|
||||
Anim_Comets(AnimationLooping, ledSettings[0].leds, ledSettings[0].size, tripple_colorPacks[AnimEvent.AnimationIndex - 41], 40, 85, RANDOM_DECAY, 2);
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
// Snakes
|
||||
case 50:
|
||||
case 50: {
|
||||
Anim_Snakes(AnimationLooping, ledSettings[0].leds, ledSettings[0].size, colorPack_RAINBOW, 50);
|
||||
break;
|
||||
case 51 ... 58:
|
||||
}
|
||||
case 51 ... 58: {
|
||||
Anim_Snakes(AnimationLooping, ledSettings[0].leds, ledSettings[0].size, single_colorPacks[AnimEvent.AnimationIndex - 51], 60, 6);
|
||||
break;
|
||||
case 59 ... 67:
|
||||
}
|
||||
case 59 ... 67: {
|
||||
Anim_Snakes(AnimationLooping, ledSettings[0].leds, ledSettings[0].size, double_colorPacks[AnimEvent.AnimationIndex - 59], 60, 3);
|
||||
break;
|
||||
case 68 ... 76:
|
||||
}
|
||||
case 68 ... 76: {
|
||||
Anim_Snakes(AnimationLooping, ledSettings[0].leds, ledSettings[0].size, tripple_colorPacks[AnimEvent.AnimationIndex - 68], 60, 2);
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
// Sectors
|
||||
case 77:
|
||||
case 77: {
|
||||
Anim_Color_Sectors(AnimationLooping, ledSettings[0].leds, ledSettings[0].size, colorPack_RAINBOW, NO_GAPS, 1, 40, 90);
|
||||
break;
|
||||
case 78 ... 86:
|
||||
}
|
||||
case 78 ... 86: {
|
||||
Anim_Color_Sectors(AnimationLooping, ledSettings[0].leds, ledSettings[0].size, double_colorPacks[AnimEvent.AnimationIndex - 78], NO_GAPS, 3, 40, 90);
|
||||
break;
|
||||
case 87 ... 95:
|
||||
}
|
||||
case 87 ... 95: {
|
||||
Anim_Color_Sectors(AnimationLooping, ledSettings[0].leds, ledSettings[0].size, tripple_colorPacks[AnimEvent.AnimationIndex - 87], NO_GAPS, 2, 40, 90);
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
// Dashes
|
||||
case 96:
|
||||
case 96:{
|
||||
Anim_Color_Sectors(AnimationLooping, ledSettings[0].leds, ledSettings[0].size, colorPack_RAINBOW, WITH_GAPS, 1, 40, 90);
|
||||
break;
|
||||
case 97 ... 104:
|
||||
}
|
||||
case 97 ... 104:{
|
||||
Anim_Color_Sectors(AnimationLooping, ledSettings[0].leds, ledSettings[0].size, single_colorPacks[AnimEvent.AnimationIndex - 97], WITH_GAPS, 6, 40, 90);
|
||||
break;
|
||||
case 105 ... 113:
|
||||
}
|
||||
case 105 ... 113:{
|
||||
Anim_Color_Sectors(AnimationLooping, ledSettings[0].leds, ledSettings[0].size, double_colorPacks[AnimEvent.AnimationIndex - 105], WITH_GAPS, 3, 40, 90);
|
||||
break;
|
||||
case 114 ... 122:
|
||||
}
|
||||
case 114 ... 122:{
|
||||
Anim_Color_Sectors(AnimationLooping, ledSettings[0].leds, ledSettings[0].size, tripple_colorPacks[AnimEvent.AnimationIndex - 114], WITH_GAPS, 2, 40, 90);
|
||||
break;
|
||||
default:
|
||||
}
|
||||
default:{
|
||||
ESP_LOGW(tag, "Loop default");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
AnimationLooping = false;
|
||||
@ -643,7 +571,7 @@ void RGB_Lights_Control_Task(void *parameters){
|
||||
ledSettings[0].shift = AnimEvent.data.data[0];
|
||||
|
||||
ESP_LOGD(tag, "Set Shift: %d", ledSettings[0].shift);
|
||||
vTaskDelay(25 / portTICK_PERIOD_MS);
|
||||
vTaskDelay(pdMS_TO_TICKS(25));
|
||||
setPixel1(ledSettings[0], 0, CRGB::White);
|
||||
|
||||
FastLED.show();
|
||||
@ -666,15 +594,25 @@ void RGB_Lights_Control_Task(void *parameters){
|
||||
FastLED.show();
|
||||
break;
|
||||
case 1 ... 5: { // Timed Fill Animations
|
||||
int timeDuration = AnimEvent.AnimationIndex * 1000 - 400;
|
||||
int whiteDelay = timeDuration - 1000;
|
||||
if (whiteDelay < 800) whiteDelay = 800; // minimum 8 seconds
|
||||
Anim_TimedFill_Flash(AnimationLooping, ledSettings[0].leds, ledSettings[0].size, pwmOutputs[0], &sys_settings.pwmOutSettings[0], whiteDelay, 10000, CRGB::Black, CRGB::White, timeDuration, ledSettings[0].shift);
|
||||
float tempMax = -1;
|
||||
if(AnimEvent.AnimationIndex == 1 && sys_settings.rampLightSettings[0].max > 70.0) {
|
||||
tempMax = sys_settings.rampLightSettings[0].max; // preserve user setting if higher than 70
|
||||
sys_settings.rampLightSettings[0].max = 70.0;
|
||||
}
|
||||
int timeDuration = (AnimEvent.AnimationIndex * 1000) - 100;
|
||||
int whiteDelay = timeDuration - 1000;
|
||||
if (whiteDelay < 0) whiteDelay = 0;
|
||||
Anim_TimedFill_Flash(AnimationLooping, ledSettings[0].leds, ledSettings[0].size, pwmOutputs[sys_settings.rampLightSettings[0].pwmOutIndex], &sys_settings.rampLightSettings[0], whiteDelay, 20000, CRGB::Black, CRGB(CRGB::White).nscale8(180), timeDuration, ledSettings[0].shift);
|
||||
|
||||
// restore ramp light max if it was changed
|
||||
if(tempMax > 0){
|
||||
sys_settings.rampLightSettings[0].max = tempMax; // restore user setting
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 6:
|
||||
// RGB White and Dedicated White all on with timeout and brightness reduction
|
||||
Anim_SolidWhite(AnimationLooping, ledSettings[0].leds, pwmOutputs[0], ledSettings[0].size, 240, 30000);
|
||||
Anim_SolidWhite(AnimationLooping, ledSettings[0].leds, pwmOutputs[sys_settings.rampLightSettings[0].pwmOutIndex], ledSettings[0].size, 240, 30000);
|
||||
break;
|
||||
case 7:
|
||||
Anim_Rainbow(AnimationLooping, ledSettings[0].leds, ledSettings[0].size, 60);
|
||||
@ -766,7 +704,6 @@ void RGB_Lights_Control_Task(void *parameters){
|
||||
|
||||
|
||||
void SetAndSaveUserSettings(USER_SETTINGS &userSettings) {
|
||||
|
||||
// Apply the settings to sys_settings
|
||||
sys_settings.limitedMode = userSettings.limitedMode;
|
||||
|
||||
|
||||
@ -14,12 +14,15 @@
|
||||
|
||||
static const char* tag = "anims";
|
||||
|
||||
typedef struct{
|
||||
float minSpeed;
|
||||
float maxSpeed;
|
||||
int rampCycles;
|
||||
}SPEED_PROPERTIES;
|
||||
//typedef struct{
|
||||
// float minSpeed;
|
||||
// float maxSpeed;
|
||||
// int rampCycles;
|
||||
//}SPEED_PROPERTIES;
|
||||
|
||||
ANIM_FIRE fireSettings; // = { FIRE_COOLING, FIRE_SPARKING, FIRE_brightness };
|
||||
ANIM_COMET cometSettings; // = { 30, 20, 0.2f, 4, 1 }; // Use 0 instead of 0.2 for integer field
|
||||
ANIM_SNAKES snakeSettings; // = { 30, 4, 1 };
|
||||
|
||||
void Animation_Init(void){
|
||||
// Create Palettes
|
||||
@ -482,9 +485,6 @@ void Anim_Rainbow(bool volatile& activeFlag, CRGB* leds, int size, int speed){
|
||||
}
|
||||
|
||||
// Fire parameters (adjustable)
|
||||
const uint8_t FIRE_COOLING = 66;
|
||||
const uint8_t FIRE_SPARKING = 55;
|
||||
const uint8_t FIRE_brightness = 240;
|
||||
|
||||
void Anim_Fire(bool volatile& activeFlag, CRGB* leds, int size, int speed, const CRGBPalette16& firePalette, int shift = 0) {
|
||||
if (!leds || size <= 0) return;
|
||||
@ -504,7 +504,7 @@ void Anim_Fire(bool volatile& activeFlag, CRGB* leds, int size, int speed, const
|
||||
Animation_Loop(activeFlag, speed, [&]() -> int {
|
||||
// Random cooling
|
||||
for(int i = 0; i < halfSize; i++) {
|
||||
heat[i] = qsub8(heat[i], random8(0, ((FIRE_COOLING * 10) / halfSize) + 2));
|
||||
heat[i] = qsub8(heat[i], random8(0, ((fireSettings.cooling * 10) / halfSize) + 2));
|
||||
}
|
||||
|
||||
// Heat rises and diffuses
|
||||
@ -513,7 +513,7 @@ void Anim_Fire(bool volatile& activeFlag, CRGB* leds, int size, int speed, const
|
||||
}
|
||||
|
||||
// Randomly ignite new sparks at bottom
|
||||
if(random8() < FIRE_SPARKING) {
|
||||
if(random8() < fireSettings.sparking) {
|
||||
// ensure y is in-bounds for small strips
|
||||
y = min<int>(random8(7), halfSize - 1);
|
||||
heat[y] = qadd8(heat[y], random8(160, 240));
|
||||
@ -522,7 +522,7 @@ void Anim_Fire(bool volatile& activeFlag, CRGB* leds, int size, int speed, const
|
||||
// Map heat to colors with mirroring and shifting
|
||||
for(int j = 0; j < halfSize; j++) {
|
||||
colorindex = scale8(heat[j], 240);
|
||||
color = ColorFromPalette(firePalette, colorindex, FIRE_brightness, LINEARBLEND);
|
||||
color = ColorFromPalette(firePalette, colorindex, fireSettings.brightness, LINEARBLEND);
|
||||
|
||||
// Apply shift and wrap around
|
||||
pos1 = (j + shift + size) % size;
|
||||
@ -639,8 +639,9 @@ void Anim_Color_Sectors(bool volatile& activeFlag, CRGB* leds, int size, const C
|
||||
/********************************************************************************
|
||||
* Comets Animation
|
||||
*******************************************************************************/
|
||||
|
||||
#define COMET_SIZE_FACTOR 0.2
|
||||
#define COMET_FADE_FACTOR1 32 /* longer tail */
|
||||
#define COMET_FADE_FACTOR1 16 /* longer tail */
|
||||
#define COMET_FADE_FACTOR2 192 /* shorter tail */
|
||||
//#define COMET_FADE_FACTOR COMET_FADE_FACTOR2
|
||||
#define MAX_COMETS 8 // Maximum number of comets supported
|
||||
@ -927,7 +928,7 @@ void Anim_TimedFill(bool volatile& activeFlag, CRGB* leds, int size, CRGB baseCo
|
||||
}
|
||||
|
||||
|
||||
void Anim_TimedFill_Flash(bool volatile& activeFlag, CRGB* leds, int size, PWM_Output* pwmOut, PWM_OUT_SETTINGS* pwmSettings, int pwmOutDelay, int flashTimeout, CRGB baseCol, CRGB fillCol, int totalDurationMs, int shift)
|
||||
void Anim_TimedFill_Flash(bool volatile& activeFlag, CRGB* leds, int size, PWM_Output* pwmOut, RAMP_LIGHT_SETTINGS* pwmSettings, int pwmOutDelay, int flashTimeout, CRGB baseCol, CRGB fillCol, int totalDurationMs, int shift)
|
||||
{
|
||||
if (!leds || size <= 1 || totalDurationMs <= 0 || !pwmOut || !pwmSettings) return;
|
||||
|
||||
@ -996,6 +997,7 @@ void Anim_TimedFill_Flash(bool volatile& activeFlag, CRGB* leds, int size, PWM_O
|
||||
pwmOut->setOutput(pwmValue);
|
||||
}
|
||||
}
|
||||
|
||||
// Phase 2: Animation complete, start flash timeout
|
||||
else if (!flashTimeoutStarted) {
|
||||
flashTimeoutStarted = true;
|
||||
@ -1214,12 +1216,13 @@ void Anim_TheaterChase(bool volatile& activeFlag, CRGB* leds, int size, const CO
|
||||
|
||||
|
||||
#define SNAKE_CYCLES_PER_ROTATION 4
|
||||
#define MAX_SNAKES 32
|
||||
|
||||
void Anim_Snakes(bool volatile& activeFlag, CRGB* leds, int size, const COLOR_PACK& colorPack, int speed , int multiplier) {
|
||||
if (!leds || size <= 0 || colorPack.size <= 0 || multiplier <= 0) return;
|
||||
|
||||
// Determine number of snakes (colors * multiplier), cap to a safe maximum
|
||||
const int USER_NUM = colorPack.size * multiplier;
|
||||
const int MAX_SNAKES = 32;
|
||||
int numSnakes = USER_NUM;
|
||||
if (numSnakes > MAX_SNAKES) numSnakes = MAX_SNAKES;
|
||||
if (numSnakes <= 0) return;
|
||||
@ -1369,7 +1372,7 @@ void Anim_Birds(bool volatile& activeFlag, CRGB* leds, int size, const COLOR_PAC
|
||||
|
||||
// Determine number of snakes (colors * multiplier), cap to a safe maximum
|
||||
const int USER_NUM = colorPack.size * multiplier;
|
||||
const int MAX_SNAKES = 32;
|
||||
//const int MAX_SNAKES = 32;
|
||||
int numSnakes = USER_NUM;
|
||||
if (numSnakes > MAX_SNAKES) numSnakes = MAX_SNAKES;
|
||||
if (numSnakes <= 0) return;
|
||||
|
||||
@ -909,7 +909,7 @@ void startFirmwareUpdateTask(AsyncEventSource* evProg) {
|
||||
return;
|
||||
}
|
||||
// Create task with higher priority (3) and optimized stack size
|
||||
xTaskCreate(firmwareUpdateTask, "FirmwareUpdate", 1024*6, NULL, 3, &Update_Task_Handle);
|
||||
xTaskCreate(firmwareUpdateTask, "FirmwareUpdate", 1024*8, NULL, 3, &Update_Task_Handle);
|
||||
}
|
||||
|
||||
void firmwareUpdateTask(void* parameter) {
|
||||
|
||||
@ -70,7 +70,6 @@ void PWM_Output::setOutput(float duty){
|
||||
this->currDuty = duty;
|
||||
}
|
||||
|
||||
|
||||
void PWM_Output::setFreq(uint32_t fq){
|
||||
uint32_t newFreq;
|
||||
if(this->freq != fq){
|
||||
|
||||
@ -14,7 +14,6 @@ RAMP_LIGHT::RAMP_LIGHT(OneButton* button, PWM_Output* pwmOutput, float min, floa
|
||||
button->attachLongPressStop([](void* context) { static_cast<RAMP_LIGHT*>(context)->longPressStop(); }, this);
|
||||
button->attachDuringLongPress([](void* context) { static_cast<RAMP_LIGHT*>(context)->duringLongPress(); }, this);
|
||||
|
||||
|
||||
if(min < 0.0) this->min = 0.0;
|
||||
if(max > 100.0) this->max = 100.0;
|
||||
if(this->max < this->min) this->max = this->min;
|
||||
|
||||
@ -53,10 +53,9 @@ void printTaskInfo(TaskStatus_t taskStatus) {
|
||||
uint32_t ulTotalRunTime = taskStatus.ulRunTimeCounter;
|
||||
uint32_t ulStatsAsPercentage = (ulTotalRunTime * 100) / ulTotalRunTime; // Total runtime equals 100%
|
||||
|
||||
ESP_LOGI(tag, "TaskInfo: %s\t%u\t%u\t%u\t%u%%",
|
||||
ESP_LOGI(tag, "TaskInfo: %s\t%u\t%u\t%u%%",
|
||||
taskStatus.pcTaskName,
|
||||
taskStatus.uxCurrentPriority,
|
||||
taskStatus.xCoreID,
|
||||
configMINIMAL_STACK_SIZE - taskStatus.usStackHighWaterMark,
|
||||
ulStatsAsPercentage);
|
||||
}
|
||||
|
||||
151
src/main.cpp
151
src/main.cpp
@ -70,19 +70,16 @@ static const char *tag = "main";
|
||||
|
||||
// Timer handles for periodic tasks
|
||||
TimerHandle_t buttonScanTimer = NULL;
|
||||
#define buttonScanInterval 10 // ms
|
||||
|
||||
TimerHandle_t temperatureTimer = NULL;
|
||||
TimerHandle_t statusLedTimer = NULL;
|
||||
#define statusLedInterval 500 // ms
|
||||
|
||||
TimerHandle_t upgradeHeartbeatTimer = NULL;
|
||||
#define upgradeHeartbeatInterval 5000 // ms
|
||||
|
||||
TimerHandle_t diagnosticsTimer = NULL;
|
||||
#define diagnosticsInterval 60000 // ms
|
||||
|
||||
TimerHandle_t analogInputTimer = NULL;
|
||||
|
||||
#define buttonScanInterval 5 // ms
|
||||
#define statusLedInterval 500 // ms
|
||||
#define upgradeHeartbeatInterval 5000 // ms
|
||||
#define diagnosticsInterval 60000 // ms
|
||||
#define analogInputInterval 3000 // ms
|
||||
|
||||
|
||||
@ -91,11 +88,27 @@ void setupLogLevels(esp_log_level_t logLevel);
|
||||
|
||||
// Timer callback functions
|
||||
void ButtonScanCallback(TimerHandle_t xTimer) {
|
||||
for (int i = 0; i < 3; i++) {
|
||||
if (boardButtons[i] != NULL) {
|
||||
boardButtons[i]->tick();
|
||||
}
|
||||
static int btnIndex = 0;
|
||||
|
||||
switch(btnIndex){
|
||||
case 0:
|
||||
if (boardButtons[0] != NULL) {
|
||||
boardButtons[0]->tick();
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
if (boardButtons[1] != NULL) {
|
||||
boardButtons[1]->tick();
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
if (boardButtons[2] != NULL) {
|
||||
boardButtons[2]->tick();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
btnIndex = (btnIndex + 1) % 3;
|
||||
}
|
||||
|
||||
void TemperatureCallback(TimerHandle_t xTimer) {
|
||||
@ -142,9 +155,8 @@ void checkLEDCChannels()
|
||||
}
|
||||
}
|
||||
|
||||
#define Button1Pin 8
|
||||
void setup()
|
||||
{
|
||||
//#define Button1Pin 8
|
||||
void setup(){
|
||||
bool UpgradeMode = false;
|
||||
|
||||
// Serial Port
|
||||
@ -157,31 +169,41 @@ void setup()
|
||||
sys_settings.ledStripSettings[0] = &ledSettings[0];
|
||||
sys_settings.ledStripSettings[1] = &ledSettings[1];
|
||||
|
||||
// Set Logging Levels
|
||||
// esp_log_level_t logLevel = ESP_LOG_INFO;
|
||||
// pinMode(Button1Pin, INPUT); // Button1
|
||||
// if(!digitalRead(Button1Pin)){
|
||||
// logLevel = ESP_LOG_VERBOSE;
|
||||
//}
|
||||
// setupLogLevels(logLevel);
|
||||
setupLogLevels(ESP_LOG_INFO);
|
||||
|
||||
// chip id, mac,
|
||||
print_chip_info();
|
||||
|
||||
// Init LittleFS
|
||||
Init_File_System();
|
||||
|
||||
// Print all system files
|
||||
if (digitalRead(sys_settings.boardPins.btn[1]) == LOW){
|
||||
printAllSystemFiles();
|
||||
}
|
||||
|
||||
String board_file_path;
|
||||
Get_Board_and_Booth_File_Paths("/system/system.json", board_file_path, booth_file_path);
|
||||
|
||||
// Load Board Pins
|
||||
Load_Board_Pins(sys_settings.boardPins, board_file_path);
|
||||
esp_log_level_t logLevel = ESP_LOG_INFO;
|
||||
if (digitalRead(sys_settings.boardPins.btn[1]) == LOW) {
|
||||
logLevel = ESP_LOG_DEBUG;
|
||||
}
|
||||
|
||||
Serial.print("Log Level: ");
|
||||
Serial.print(logLevel);
|
||||
Serial.print(" (");
|
||||
switch (logLevel) {
|
||||
case ESP_LOG_NONE: Serial.print("NONE"); break;
|
||||
case ESP_LOG_ERROR: Serial.print("1-ERROR"); break;
|
||||
case ESP_LOG_WARN: Serial.print("2-WARN"); break;
|
||||
case ESP_LOG_INFO: Serial.print("3-INFO"); break;
|
||||
case ESP_LOG_DEBUG: Serial.print("4-DEBUG"); break;
|
||||
case ESP_LOG_VERBOSE: Serial.print("5-VERBOSE"); break;
|
||||
default: Serial.print("UNKNOWN"); break;
|
||||
}
|
||||
Serial.println(")");
|
||||
setupLogLevels(logLevel);
|
||||
|
||||
// chip id, mac,
|
||||
print_chip_info();
|
||||
|
||||
// Print all system files
|
||||
if (digitalRead(sys_settings.boardPins.btn[1]) == LOW){
|
||||
printAllSystemFiles();
|
||||
}
|
||||
|
||||
// Set status pins off
|
||||
setStatusPin1(false);
|
||||
@ -229,7 +251,7 @@ void setup()
|
||||
upgradeHeartbeatTimer = xTimerCreate("UpgradeHeartbeat", pdMS_TO_TICKS(5000), pdTRUE, NULL, UpgradeHeartbeatCallback);
|
||||
}
|
||||
else {
|
||||
ESP_LOGI(tag, "Enabling BLE, No Update Service");
|
||||
ESP_LOGW(tag, "Enabling BLE, No Update Service");
|
||||
Init_BleServer(true, false); // Dont start the Upgrade service
|
||||
}
|
||||
|
||||
@ -259,11 +281,11 @@ void setup()
|
||||
#endif
|
||||
|
||||
// Start the timers
|
||||
//if (buttonScanTimer) xTimerStart(buttonScanTimer, 100);
|
||||
if (temperatureTimer && sys_settings.tSensorSettings.enabled) xTimerStart(temperatureTimer, 100);
|
||||
if (statusLedTimer) xTimerStart(statusLedTimer, 0);
|
||||
if (buttonScanTimer) xTimerStart(buttonScanTimer, 200);
|
||||
if (temperatureTimer && sys_settings.tSensorSettings.enabled) xTimerStart(temperatureTimer, 500);
|
||||
if (statusLedTimer) xTimerStart(statusLedTimer, 100);
|
||||
if (upgradeHeartbeatTimer && UpgradeMode) xTimerStart(upgradeHeartbeatTimer, upgradeHeartbeatInterval);
|
||||
if (analogInputTimer) xTimerStart(analogInputTimer, 0);
|
||||
if (analogInputTimer) xTimerStart(analogInputTimer, 150);
|
||||
|
||||
#if FREERTOS_DIAGNOSTICS
|
||||
if (diagnosticsTimer) xTimerStart(diagnosticsTimer, diagnosticsInterval);
|
||||
@ -281,61 +303,11 @@ void setup()
|
||||
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
// Animation TestMode Timeout (keep in loop as it's event-driven)
|
||||
#if LEDS_ENABLED
|
||||
if (animStatus.EventTestCountdown)
|
||||
{
|
||||
if (--animStatus.EventTestCountdown == 0)
|
||||
{
|
||||
ESP_LOGD(tag, "Test Timeout trigger");
|
||||
PostLastNormalEvent();
|
||||
if (Strip1_Task_Handle)
|
||||
{
|
||||
xTaskNotifyGive(Strip1_Task_Handle);
|
||||
} // trigger exit of animation loop
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
// Reboot requested (keep in loop as it's a state-based countdown)
|
||||
#if WIFI_ENABLED
|
||||
if (RebootSystem)
|
||||
{
|
||||
if (--RebootSystem == 0)
|
||||
{
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
#if BUZZER_ENABLED
|
||||
Buzzer_Play_Tune(TUNE_LOWEEP); // blocking
|
||||
#endif
|
||||
vTaskDelay(200);
|
||||
}
|
||||
ESP_LOGW(tag, "Restarting...");
|
||||
vTaskDelay(200);
|
||||
ESP.restart();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
for (int i = 0; i < 3; i++) {
|
||||
if (boardButtons[i] != NULL) {
|
||||
boardButtons[i]->tick();
|
||||
}
|
||||
}
|
||||
vTaskDelay(buttonScanInterval);
|
||||
*/
|
||||
|
||||
// Small delay to prevent busy-waiting
|
||||
//vTaskDelay(pdMS_TO_TICKS(100));
|
||||
|
||||
void loop(){
|
||||
vTaskDelay(portMAX_DELAY);
|
||||
}
|
||||
|
||||
void setupLogLevels(esp_log_level_t logLevel)
|
||||
{
|
||||
void setupLogLevels(esp_log_level_t logLevel){
|
||||
// Options: ESP_LOG_ERROR,ESP_LOG_WARN,ESP_LOG_INFO,ESP_LOG_DEBUG,ESP_LOG_VERBOSE
|
||||
esp_log_level_set("*", logLevel);
|
||||
esp_log_level_set("fs", logLevel);
|
||||
@ -353,6 +325,7 @@ void setupLogLevels(esp_log_level_t logLevel)
|
||||
esp_log_level_set("oled", logLevel);
|
||||
esp_log_level_set("trx433", logLevel);
|
||||
esp_log_level_set("tsensor", logLevel);
|
||||
esp_log_level_set("my_device", logLevel);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -17,13 +17,13 @@ static bool isValidGpio(int pin) {
|
||||
if (pin < 0 || pin > 48)
|
||||
return false;
|
||||
switch (pin) {
|
||||
case 19: // USB D-
|
||||
case 20: // USB D+
|
||||
case 45: // strapping
|
||||
case 46: // strapping
|
||||
return false;
|
||||
default:
|
||||
return true;
|
||||
case 19: // USB D-
|
||||
case 20: // USB D+
|
||||
case 45: // strapping
|
||||
case 46: // strapping
|
||||
return false;
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@ -81,24 +81,33 @@ bool Load_Board_Pins(BOARD_PINS &boardPins, const String &path) {
|
||||
auto clampPin = [](int v) { return isValidGpio(v) ? v : -1; };
|
||||
boardPins.rgb1 = clampPin(boardPins.rgb1);
|
||||
boardPins.rgb2 = clampPin(boardPins.rgb2);
|
||||
|
||||
for (int i = 0; i < 3; i++)
|
||||
boardPins.btn[i] = clampPin(boardPins.btn[i]);
|
||||
|
||||
boardPins.buzzer = clampPin(boardPins.buzzer);
|
||||
|
||||
for (int i = 0; i < 5; i++)
|
||||
boardPins.touch[i] = clampPin(boardPins.touch[i]);
|
||||
|
||||
boardPins.shield = clampPin(boardPins.shield);
|
||||
|
||||
for (int i = 0; i < 4; i++)
|
||||
boardPins.relay[i] = clampPin(boardPins.relay[i]);
|
||||
|
||||
for (int i = 0; i < 2; i++)
|
||||
boardPins.stat[i] = clampPin(boardPins.stat[i]);
|
||||
|
||||
boardPins.adc1 = clampPin(boardPins.adc1);
|
||||
boardPins.oled_dc = clampPin(boardPins.oled_dc);
|
||||
boardPins.oled_rst = clampPin(boardPins.oled_rst);
|
||||
boardPins.oled_mosi = clampPin(boardPins.oled_mosi);
|
||||
boardPins.oled_sck = clampPin(boardPins.oled_sck);
|
||||
boardPins.oled_cs = clampPin(boardPins.oled_cs);
|
||||
|
||||
for (int i = 0; i < 2; i++)
|
||||
boardPins.ext[i] = clampPin(boardPins.ext[i]);
|
||||
|
||||
boardPins.rf433tx = clampPin(boardPins.rf433tx);
|
||||
boardPins.rf433rx = clampPin(boardPins.rf433rx);
|
||||
|
||||
@ -107,40 +116,17 @@ bool Load_Board_Pins(BOARD_PINS &boardPins, const String &path) {
|
||||
}
|
||||
|
||||
void Init_Board_Basic(BOARD_PINS &boardPins) {
|
||||
|
||||
if (boardPins.stat[0] >= 0) {
|
||||
pinMode(boardPins.stat[0], OUTPUT);
|
||||
}
|
||||
if (boardPins.stat[1] >= 0) {
|
||||
pinMode(boardPins.stat[1], OUTPUT);
|
||||
}
|
||||
if (boardPins.btn[0] >= 0) {
|
||||
pinMode(boardPins.btn[0], INPUT_PULLUP);
|
||||
}
|
||||
if (boardPins.btn[1] >= 0) {
|
||||
pinMode(boardPins.btn[1], INPUT_PULLUP);
|
||||
}
|
||||
if (boardPins.btn[2] >= 0) {
|
||||
pinMode(boardPins.btn[2], INPUT);
|
||||
}
|
||||
if (boardPins.rgb1 >= 0) {
|
||||
pinMode(boardPins.rgb1, OUTPUT);
|
||||
}
|
||||
if (boardPins.rgb2 >= 0) {
|
||||
pinMode(boardPins.rgb2, OUTPUT);
|
||||
}
|
||||
if (boardPins.relay[0] >= 0) {
|
||||
pinMode(boardPins.relay[0], OUTPUT);
|
||||
}
|
||||
if (boardPins.relay[1] >= 0) {
|
||||
pinMode(boardPins.relay[1], OUTPUT);
|
||||
}
|
||||
if (boardPins.relay[2] >= 0) {
|
||||
pinMode(boardPins.relay[2], OUTPUT);
|
||||
}
|
||||
if (boardPins.relay[3] >= 0) {
|
||||
pinMode(boardPins.relay[3], OUTPUT);
|
||||
}
|
||||
if (boardPins.stat[0] >= 0) { pinMode(boardPins.stat[0], OUTPUT); }
|
||||
if (boardPins.stat[1] >= 0) { pinMode(boardPins.stat[1], OUTPUT); }
|
||||
if (boardPins.btn[0] >= 0) { pinMode(boardPins.btn[0], INPUT_PULLUP); }
|
||||
if (boardPins.btn[1] >= 0) { pinMode(boardPins.btn[1], INPUT_PULLUP); }
|
||||
if (boardPins.btn[2] >= 0) { pinMode(boardPins.btn[2], INPUT); }
|
||||
if (boardPins.rgb1 >= 0) { pinMode(boardPins.rgb1, OUTPUT); }
|
||||
if (boardPins.rgb2 >= 0) { pinMode(boardPins.rgb2, OUTPUT); }
|
||||
if (boardPins.relay[0] >= 0) { pinMode(boardPins.relay[0], OUTPUT); }
|
||||
if (boardPins.relay[1] >= 0) { pinMode(boardPins.relay[1], OUTPUT); }
|
||||
if (boardPins.relay[2] >= 0) { pinMode(boardPins.relay[2], OUTPUT); }
|
||||
if (boardPins.relay[3] >= 0) { pinMode(boardPins.relay[3], OUTPUT); }
|
||||
|
||||
ESP_LOGI(tag, "Board pins initialized...");
|
||||
}
|
||||
|
||||
@ -9,57 +9,20 @@ OneButton *boardButtons[3] = { nullptr, nullptr, nullptr };
|
||||
|
||||
void Init_ButtonEvents(int8_t (&pin)[3]){
|
||||
// Initialize buttons if pins are valid and not already initialized
|
||||
if (pin[0] >= 0) {
|
||||
if (boardButtons[0] == nullptr) {
|
||||
boardButtons[0] = new OneButton(pin[0], true, true);
|
||||
ESP_LOGI(tag, "Button1 Events, pin=%d", pin[0]);
|
||||
} else {
|
||||
ESP_LOGW(tag, "Button1 already initialized (pin=%d)", pin[0]);
|
||||
}
|
||||
}
|
||||
if (pin[1] >= 0) {
|
||||
if (boardButtons[1] == nullptr) {
|
||||
boardButtons[1] = new OneButton(pin[1], true, true);
|
||||
ESP_LOGI(tag, "Button2 Events, pin=%d", pin[1]);
|
||||
} else {
|
||||
ESP_LOGW(tag, "Button2 already initialized (pin=%d)", pin[1]);
|
||||
}
|
||||
}
|
||||
if (pin[2] >= 0) {
|
||||
if (boardButtons[2] == nullptr) {
|
||||
boardButtons[2] = new OneButton(pin[2], true, false);
|
||||
ESP_LOGI(tag, "Button3 Events, pin=%d", pin[2]);
|
||||
} else {
|
||||
ESP_LOGW(tag, "Button3 already initialized (pin=%d)", pin[2]);
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
if (pin[i] >= 0) {
|
||||
if (boardButtons[i] == nullptr) {
|
||||
// For button 3 (index 2), set pullup to false, others true
|
||||
bool pullup = (i == 2) ? false : true;
|
||||
boardButtons[i] = new OneButton(pin[i], true, pullup);
|
||||
ESP_LOGI(tag, "Button%d Events, pin=%d", i + 1, pin[i]);
|
||||
} else {
|
||||
ESP_LOGW(tag, "Button%d already initialized (pin=%d)", i + 1, pin[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
if(boardButtons[0] != NULL){
|
||||
//boardButtons[0]->setDebounceTicks(DEBOUCE_TIME); // just below the update period to guarantee 1 sample delay
|
||||
boardButtons[0]->attachClick(btn1_click);
|
||||
boardButtons[0]->attachDoubleClick(btn1_doubleClick);
|
||||
boardButtons[0]->attachLongPressStart(btn1_LongPressStart);
|
||||
boardButtons[0]->attachLongPressStop(btn1_LongPressStop);
|
||||
boardButtons[0]->attachDuringLongPress(btn1_DuringLongPress);
|
||||
}
|
||||
else {
|
||||
ESP_LOGD(tag, "Button1 Not Initialized");
|
||||
}
|
||||
|
||||
if(boardButtons[1] != NULL){
|
||||
//boardButtons[1]->setDebounceTicks(DEBOUCE_TIME);
|
||||
boardButtons[1]->attachClick(btn2_click);
|
||||
boardButtons[1]->attachDoubleClick(btn2_doubleClick);
|
||||
boardButtons[1]->attachLongPressStart(btn2_LongPressStart);
|
||||
boardButtons[1]->attachLongPressStop(btn2_LongPressStop);
|
||||
boardButtons[1]->attachDuringLongPress(btn2_DuringLongPress);
|
||||
}
|
||||
else {
|
||||
ESP_LOGD(tag, "Button2 Not Initialized");
|
||||
}
|
||||
*/
|
||||
|
||||
if(boardButtons[2] != NULL){
|
||||
//boardButtons[2]->setDebounceTicks(DEBOUCE_TIME);
|
||||
boardButtons[2]->attachClick(btn3_click);
|
||||
@ -72,17 +35,10 @@ void Init_ButtonEvents(int8_t (&pin)[3]){
|
||||
else {
|
||||
ESP_LOGW(tag, "Button3 Not Initialized");
|
||||
}
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
void Update_Buttons() {
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
if (boardButtons[i] != nullptr) {
|
||||
boardButtons[i]->tick();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void btn1_click() {
|
||||
//IncrementEventIndex();
|
||||
//Pulse_LED_Status(150);
|
||||
@ -112,7 +68,7 @@ void btn2_click() {
|
||||
//Pulse_LED_Status(150);
|
||||
//Buzzer_Beep(150);
|
||||
// send packet
|
||||
sendUpdateMessage("testing....", false, -1);
|
||||
//sendUpdateMessage("testing....", false, -1);
|
||||
ESP_LOGD(tag, "btn2 1x");
|
||||
}
|
||||
|
||||
@ -141,7 +97,7 @@ void btn3_click() {
|
||||
}
|
||||
|
||||
void btn3_doubleClick() {
|
||||
bleUpgrade_send_message("Hello....3");
|
||||
//bleUpgrade_send_message("Hello....3");
|
||||
ESP_LOGD(tag, "btn3 2x");
|
||||
}
|
||||
|
||||
|
||||
@ -18,6 +18,7 @@
|
||||
#include <esp_system.h>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include "Animations.h"
|
||||
|
||||
static const char *tag = "my_device";
|
||||
|
||||
@ -33,8 +34,6 @@ float prevPowerVin = 0.0;
|
||||
float PowerVin = 0.0;
|
||||
|
||||
|
||||
|
||||
// TODO Restore original setOutput code..
|
||||
#define RELAY_RES 10
|
||||
void Init_PWM_Outputs(int8_t (&pin)[4], PWM_OUT_SETTINGS (&pwmSettings)[4]) {
|
||||
// Delete any existing objects to avoid leaks on re-init
|
||||
@ -51,36 +50,28 @@ void Init_PWM_Outputs(int8_t (&pin)[4], PWM_OUT_SETTINGS (&pwmSettings)[4]) {
|
||||
ESP_LOGE(tag, "No available LEDC channel for PWM Output%d", i);
|
||||
continue;
|
||||
}
|
||||
pwmOutputs[i] = new PWM_Output(pin[i], chIndex, RELAY_RES, pwmSettings[i].freq,
|
||||
pwmSettings[i].max, false);
|
||||
pwmOutputs[i] = new PWM_Output(pin[i], chIndex, RELAY_RES, pwmSettings[i].freq, pwmSettings[i].max, false);
|
||||
if (pwmOutputs[i]) {
|
||||
pwmOutputs[i]->setOutput(pwmSettings[i].def);
|
||||
} else {
|
||||
ESP_LOGE(tag, "Allocation failed for PWM Output%d", i);
|
||||
}
|
||||
// pwmOutputs[i]->setOutput(5.0);
|
||||
ESP_LOGI(tag, "PWM Output%d: Pin=%d, Freq=%d, ch=%d", i, pin[i], pwmSettings[i].freq,
|
||||
chIndex);
|
||||
ESP_LOGI(tag, "PWM Output%d: Pin=%d, Freq=%d, ch=%d", i, pin[i], pwmSettings[i].freq, chIndex);
|
||||
}
|
||||
}
|
||||
|
||||
void Init_Ramp_Lights(RAMP_LIGHT_SETTINGS (&settings)[2], OneButton *(&btn)[3], PWM_Output *(&pwm)[4]) {
|
||||
if (settings[0].enabled) {
|
||||
if (rampLight1) { delete rampLight1; rampLight1 = nullptr; }
|
||||
rampLight1 = new RAMP_LIGHT(btn[settings[0].btnIndex], pwm[settings[0].pwmOutIndex], settings[0].min, settings[0].max, settings[0].step);
|
||||
if (rampLight1)
|
||||
ESP_LOGD(tag, "RampLight%d: btn=%d, pwmIndex=%d, min=%f, max=%f, step=%f", 1, settings[0].btnIndex, settings[0].pwmOutIndex, settings[0].min, settings[0].max, settings[0].step);
|
||||
else
|
||||
ESP_LOGE(tag, "Failed to allocate RampLight1");
|
||||
}
|
||||
|
||||
if (settings[1].enabled) {
|
||||
if (rampLight2) { delete rampLight2; rampLight2 = nullptr; }
|
||||
rampLight2 = new RAMP_LIGHT(btn[settings[1].btnIndex], pwm[settings[1].pwmOutIndex], settings[1].min, settings[1].max, settings[1].step);
|
||||
if (rampLight2)
|
||||
ESP_LOGD(tag, "RampLight%d: btn=%d, pwmIndex=%d, min=%f, max=%f, step=%f", 2, settings[1].btnIndex, settings[1].pwmOutIndex, settings[1].min, settings[1].max, settings[1].step);
|
||||
else
|
||||
ESP_LOGE(tag, "Failed to allocate RampLight2");
|
||||
RAMP_LIGHT **rampLights[2] = { &rampLight1, &rampLight2 };
|
||||
for (int i = 0; i < 2; ++i) {
|
||||
if (settings[i].enabled) {
|
||||
if (*(rampLights[i])) { delete *(rampLights[i]); *(rampLights[i]) = nullptr; }
|
||||
*(rampLights[i]) = new RAMP_LIGHT(btn[settings[i].btnIndex], pwm[settings[i].pwmOutIndex], settings[i].min, settings[i].max, settings[i].step);
|
||||
if (*(rampLights[i]))
|
||||
ESP_LOGI(tag, "RampLight%d: btn=%d, pwmIndex=%d, min=%f, max=%f, step=%f", i + 1, settings[i].btnIndex, settings[i].pwmOutIndex, settings[i].min, settings[i].max, settings[i].step);
|
||||
else
|
||||
ESP_LOGE(tag, "Failed to allocate RampLight%d", i + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -146,14 +137,10 @@ void Load_Booth_Settings(SYS_SETTINGS &sys, const String &boothPath) {
|
||||
sizeof(sys_settings.pwmOutSettings) / sizeof(sys_settings.pwmOutSettings[0]))
|
||||
break;
|
||||
sys_settings.pwmOutSettings[pwmIndex].enabled = jsonConstrainBool(tag, obj, "en", true);
|
||||
sys_settings.pwmOutSettings[pwmIndex].freq =
|
||||
jsonConstrain<int>(tag, obj, "freq", 100, 5000, 250);
|
||||
sys_settings.pwmOutSettings[pwmIndex].min =
|
||||
jsonConstrain<float>(tag, obj, "min", 0.0, 95.0, 0.0);
|
||||
sys_settings.pwmOutSettings[pwmIndex].max =
|
||||
jsonConstrain<float>(tag, obj, "max", 5.0, 100.0, 100.0);
|
||||
sys_settings.pwmOutSettings[pwmIndex].def =
|
||||
jsonConstrain<float>(tag, obj, "default", 0.0, 100.0, 0.0);
|
||||
sys_settings.pwmOutSettings[pwmIndex].freq = jsonConstrain<int>(tag, obj, "freq", 100, 5000, 250);
|
||||
sys_settings.pwmOutSettings[pwmIndex].min = jsonConstrain<float>(tag, obj, "min", 0.0, 95.0, 0.0);
|
||||
sys_settings.pwmOutSettings[pwmIndex].max = jsonConstrain<float>(tag, obj, "max", 5.0, 100.0, 100.0);
|
||||
sys_settings.pwmOutSettings[pwmIndex].def = jsonConstrain<float>(tag, obj, "default", 0.0, 100.0, 0.0);
|
||||
sys_settings.pwmOutSettings[pwmIndex].deltaRate = 1.0;
|
||||
// sys_settings.pwmOutSettings[pwmIndex]. = jsonConstrainBool(tag, obj, "vision", true);
|
||||
pwmIndex++;
|
||||
@ -171,20 +158,13 @@ void Load_Booth_Settings(SYS_SETTINGS &sys, const String &boothPath) {
|
||||
if (rampIndex >=
|
||||
sizeof(sys_settings.rampLightSettings) / sizeof(sys_settings.rampLightSettings[0]))
|
||||
break;
|
||||
sys_settings.rampLightSettings[rampIndex].enabled =
|
||||
jsonConstrainBool(tag, obj, "en", true);
|
||||
sys_settings.rampLightSettings[rampIndex].vision =
|
||||
jsonConstrainBool(tag, obj, "vision", true);
|
||||
sys_settings.rampLightSettings[rampIndex].pwmOutIndex =
|
||||
jsonConstrain<int>(tag, obj, "relay-index", 0, 1, 0);
|
||||
sys_settings.rampLightSettings[rampIndex].btnIndex =
|
||||
jsonConstrain<int>(tag, obj, "button-index", 0, 1, 0);
|
||||
sys_settings.rampLightSettings[rampIndex].min =
|
||||
jsonConstrain<float>(tag, obj, "min", 0.0, 95.0, 0.0);
|
||||
sys_settings.rampLightSettings[rampIndex].max =
|
||||
jsonConstrain<float>(tag, obj, "max", 5.0, 100.0, 100.0);
|
||||
sys_settings.rampLightSettings[rampIndex].step =
|
||||
jsonConstrain<float>(tag, obj, "step", 0.1, 10.0, 1.5);
|
||||
sys_settings.rampLightSettings[rampIndex].enabled = jsonConstrainBool(tag, obj, "en", true);
|
||||
sys_settings.rampLightSettings[rampIndex].vision = jsonConstrainBool(tag, obj, "vision", true);
|
||||
sys_settings.rampLightSettings[rampIndex].pwmOutIndex = jsonConstrain<int>(tag, obj, "relay-index", 0, 3, 0);
|
||||
sys_settings.rampLightSettings[rampIndex].btnIndex = jsonConstrain<int>(tag, obj, "button-index", 0, 2, 0);
|
||||
sys_settings.rampLightSettings[rampIndex].min = jsonConstrain<float>(tag, obj, "min", 0.0, 95.0, 0.0);
|
||||
sys_settings.rampLightSettings[rampIndex].max = jsonConstrain<float>(tag, obj, "max", 5.0, 100.0, 100.0);
|
||||
sys_settings.rampLightSettings[rampIndex].step = jsonConstrain<float>(tag, obj, "step", 0.1, 10.0, 1.5);
|
||||
rampIndex++;
|
||||
}
|
||||
ESP_LOGI(tag, "Loaded Ramp Lights settings...");
|
||||
@ -196,20 +176,13 @@ void Load_Booth_Settings(SYS_SETTINGS &sys, const String &boothPath) {
|
||||
JsonObject sensorJson = doc["t-sensor"];
|
||||
if (!sensorJson.isNull()) {
|
||||
sys_settings.tSensorSettings.enabled = jsonConstrainBool(tag, sensorJson, "en", true);
|
||||
sys_settings.tSensorSettings.pwmIndex =
|
||||
jsonConstrain<int>(tag, sensorJson, "relay", 0, 3, 3);
|
||||
sys_settings.tSensorSettings.setpoint1 =
|
||||
jsonConstrain<float>(tag, sensorJson, "sp1", 50.0, 100.0, 80.0);
|
||||
sys_settings.tSensorSettings.setpoint2 =
|
||||
jsonConstrain<float>(tag, sensorJson, "sp2", 60.0, 110.0, 90.0);
|
||||
sys_settings.tSensorSettings.fanPower1 =
|
||||
jsonConstrain<float>(tag, sensorJson, "fan-pwr1", 0.0, 100.0, 50.0);
|
||||
sys_settings.tSensorSettings.fanPower2 =
|
||||
jsonConstrain<float>(tag, sensorJson, "fan-pwr2", 50.0, 100.0, 50.0);
|
||||
sys_settings.tSensorSettings.hyst =
|
||||
jsonConstrain<float>(tag, sensorJson, "hyst", 1.0, 10.0, 1.0);
|
||||
sys_settings.tSensorSettings.intervalMs =
|
||||
jsonConstrain<int>(tag, sensorJson, "interval", 1000, 30000, 5000);
|
||||
sys_settings.tSensorSettings.pwmIndex = jsonConstrain<int>(tag, sensorJson, "relay", 0, 3, 3);
|
||||
sys_settings.tSensorSettings.setpoint1 = jsonConstrain<float>(tag, sensorJson, "sp1", 50.0, 100.0, 80.0);
|
||||
sys_settings.tSensorSettings.setpoint2 = jsonConstrain<float>(tag, sensorJson, "sp2", 60.0, 110.0, 90.0);
|
||||
sys_settings.tSensorSettings.fanPower1 = jsonConstrain<float>(tag, sensorJson, "fan-pwr1", 0.0, 100.0, 50.0);
|
||||
sys_settings.tSensorSettings.fanPower2 = jsonConstrain<float>(tag, sensorJson, "fan-pwr2", 50.0, 100.0, 50.0);
|
||||
sys_settings.tSensorSettings.hyst = jsonConstrain<float>(tag, sensorJson, "hyst", 1.0, 10.0, 1.0);
|
||||
sys_settings.tSensorSettings.intervalMs = jsonConstrain<int>(tag, sensorJson, "interval", 1000, 30000, 5000);
|
||||
ESP_LOGI(tag, "Loaded TSensor settings...");
|
||||
ESP_LOGI(tag, " SP1: %F, SP2 %F, Hyst: %F", sys_settings.tSensorSettings.setpoint1,
|
||||
sys_settings.tSensorSettings.setpoint2, sys_settings.tSensorSettings.hyst);
|
||||
@ -225,24 +198,16 @@ void Load_Booth_Settings(SYS_SETTINGS &sys, const String &boothPath) {
|
||||
if (stripIndex >= 2)
|
||||
break;
|
||||
if (sys_settings.ledStripSettings[stripIndex]) {
|
||||
sys_settings.ledStripSettings[stripIndex]->enabled =
|
||||
jsonConstrainBool(tag, obj, "en", true);
|
||||
sys_settings.ledStripSettings[stripIndex]->size =
|
||||
jsonConstrain<int>(tag, obj, "size", 1, 250, 25);
|
||||
sys_settings.ledStripSettings[stripIndex]->chip =
|
||||
jsonConstrainString(tag, obj, "chip", "WS2812B");
|
||||
sys_settings.ledStripSettings[stripIndex]->rgbOrder =
|
||||
jsonConstrainString(tag, obj, "rgb-order", "WS2812B");
|
||||
sys_settings.ledStripSettings[stripIndex]->shift =
|
||||
jsonConstrain<int>(tag, obj, "shift", -250, 250, 0);
|
||||
sys_settings.ledStripSettings[stripIndex]->offset =
|
||||
jsonConstrain<int>(tag, obj, "offset", -250, 250, 0);
|
||||
sys_settings.ledStripSettings[stripIndex]->bright =
|
||||
jsonConstrain<int>(tag, obj, "bright", 5, 255, 200);
|
||||
sys_settings.ledStripSettings[stripIndex]->enabled = jsonConstrainBool(tag, obj, "en", true);
|
||||
sys_settings.ledStripSettings[stripIndex]->size = jsonConstrain<int>(tag, obj, "size", 1, 250, 25);
|
||||
sys_settings.ledStripSettings[stripIndex]->chip = jsonConstrainString(tag, obj, "chip", "WS2812B");
|
||||
sys_settings.ledStripSettings[stripIndex]->rgbOrder = jsonConstrainString(tag, obj, "rgb-order", "WS2812B");
|
||||
sys_settings.ledStripSettings[stripIndex]->shift = jsonConstrain<int>(tag, obj, "shift", -250, 250, 0);
|
||||
sys_settings.ledStripSettings[stripIndex]->offset = jsonConstrain<int>(tag, obj, "offset", -250, 250, 0);
|
||||
sys_settings.ledStripSettings[stripIndex]->bright = jsonConstrain<int>(tag, obj, "bright", 5, 255, 200);
|
||||
sys_settings.ledStripSettings[stripIndex]->powerDiv = 0;
|
||||
sys_settings.ledStripSettings[stripIndex]->i2sCh = 0;
|
||||
sys_settings.ledStripSettings[stripIndex]->core =
|
||||
jsonConstrain<int>(tag, obj, "core", 0, 1, 0);
|
||||
sys_settings.ledStripSettings[stripIndex]->core = jsonConstrain<int>(tag, obj, "core", 0, 1, 0);
|
||||
} else {
|
||||
ESP_LOGW(tag, "ledStripSettings[%d] is null, skipping config", stripIndex);
|
||||
}
|
||||
@ -256,27 +221,40 @@ void Load_Booth_Settings(SYS_SETTINGS &sys, const String &boothPath) {
|
||||
ESP_LOGE(tag, "Error!, %s key: strips not found..");
|
||||
}
|
||||
|
||||
// ********** BLE ***********
|
||||
JsonObject bleJson = doc["ble"];
|
||||
if (!bleJson.isNull()) {
|
||||
sys_settings.bleSettings.enabled = jsonConstrainBool(tag, bleJson, "en", true);
|
||||
sys_settings.bleSettings.name = jsonConstrainString(tag, bleJson, "name", "ATA_LIGHTS");
|
||||
|
||||
ESP_LOGI(tag, "Loaded BLE settings...");
|
||||
// Load Animation settings
|
||||
JsonObject fireAnimJson = doc["fire-animation"];
|
||||
if (!fireAnimJson.isNull()) {
|
||||
fireSettings.speed = jsonConstrain<int>(tag, fireAnimJson, "speed", 10, 100, 50);
|
||||
fireSettings.cooling = jsonConstrain<int>(tag, fireAnimJson, "cooling", 0, 255, 65);
|
||||
fireSettings.sparking = jsonConstrain<int>(tag, fireAnimJson, "sparking", 0, 255, 62);
|
||||
fireSettings.brightness = jsonConstrain<int>(tag, fireAnimJson, "brightness", 0, 255, 240);
|
||||
ESP_LOGI(tag, "Loaded Animation settings...");
|
||||
} else {
|
||||
ESP_LOGE(tag, "Error!, %s key: ble not found..", boothPath);
|
||||
ESP_LOGE(tag, "Error!, %s key: animation not found..", boothPath);
|
||||
}
|
||||
|
||||
// ********** RF Remote***********
|
||||
/*
|
||||
JsonObject rfJson = doc["wifi-ap"];
|
||||
if(!rfJson.isNull()){
|
||||
//sys_settings.rampLights[0].enabled = jsonConstrainBool(tag, wifiApJson, "en", true);
|
||||
ESP_LOGI(tag, "Loaded RF Remote settings...");
|
||||
}else{
|
||||
ESP_LOGE(tag, "Error!, %s key: wifi-ap not found..", boothPath);
|
||||
JsonObject cometsAnimJson = doc["comets-animation"];
|
||||
if (!cometsAnimJson.isNull()) {
|
||||
cometSettings.speed = jsonConstrain<int>(tag, cometsAnimJson, "speed", 10, 100, 50);
|
||||
cometSettings.minFade = jsonConstrain<int>(tag, cometsAnimJson, "min-fade", 0, 255, 66);
|
||||
cometSettings.maxFade = jsonConstrain<int>(tag, cometsAnimJson, "max-fade", 0, 255, 55);
|
||||
cometSettings.sizeFactor = jsonConstrain<float>(tag, cometsAnimJson, "size-factor", 0.0f, 1.0f, 0.2f);
|
||||
cometSettings.cycles = jsonConstrain<int>(tag, cometsAnimJson, "cycles", 1, 10, 4);
|
||||
cometSettings.count = jsonConstrain<int>(tag, cometsAnimJson, "count", 1, 10, 1);
|
||||
ESP_LOGI(tag, "Loaded Comet Animation settings...");
|
||||
} else {
|
||||
ESP_LOGE(tag, "Error!, %s key: comets-animation not found..", boothPath);
|
||||
}
|
||||
|
||||
JsonObject snakesAnimJson = doc["snakes-animation"];
|
||||
if (!snakesAnimJson.isNull()) {
|
||||
snakeSettings.speed = jsonConstrain<int>(tag, snakesAnimJson, "speed", 10, 100, 50);
|
||||
snakeSettings.cycles = jsonConstrain<int>(tag, snakesAnimJson, "cycles", 1, 10, 4);
|
||||
snakeSettings.multiplier = jsonConstrain<int>(tag, snakesAnimJson, "multiplier", 1, 10, 6);
|
||||
ESP_LOGI(tag, "Loaded Snake Animation settings...");
|
||||
} else {
|
||||
ESP_LOGE(tag, "Error!, %s key: snakes-animation not found..", boothPath);
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
void Init_ADC(void) {
|
||||
@ -289,15 +267,23 @@ void Init_ADC(void) {
|
||||
|
||||
// Enable ADC calibration
|
||||
esp_adc_cal_characteristics_t adc_chars;
|
||||
esp_adc_cal_characterize(ADC_UNIT_1, ADC_ATTEN_DB_11, ADC_WIDTH_BIT_12, 0, &adc_chars);
|
||||
const uint32_t default_vref = 1100; // mV
|
||||
esp_adc_cal_value_t used = esp_adc_cal_characterize(ADC_UNIT_1, ADC_ATTEN_DB_12, ADC_WIDTH_BIT_12, default_vref, &adc_chars);
|
||||
|
||||
// Check calibration success
|
||||
if (esp_adc_cal_check_efuse(ESP_ADC_CAL_VAL_EFUSE_TP) == ESP_OK) {
|
||||
ESP_LOGI(tag, "ADC calibration: Using Two Point values from eFuse");
|
||||
} else if (esp_adc_cal_check_efuse(ESP_ADC_CAL_VAL_EFUSE_VREF) == ESP_OK) {
|
||||
ESP_LOGI(tag, "ADC calibration: Using reference voltage from eFuse");
|
||||
} else {
|
||||
ESP_LOGW(tag, "ADC calibration: Using default reference voltage");
|
||||
switch (used) {
|
||||
case ESP_ADC_CAL_VAL_EFUSE_TP_FIT:
|
||||
ESP_LOGI(tag, "ADC calibrated using eFuse Two-Point + Fit coefficients (TP_FIT)");
|
||||
break;
|
||||
case ESP_ADC_CAL_VAL_EFUSE_TP:
|
||||
ESP_LOGI(tag, "ADC calibrated using eFuse Two-Point values (TP)");
|
||||
break;
|
||||
case ESP_ADC_CAL_VAL_EFUSE_VREF:
|
||||
ESP_LOGI(tag, "ADC calibrated using eFuse Vref");
|
||||
break;
|
||||
case ESP_ADC_CAL_VAL_DEFAULT_VREF:
|
||||
default:
|
||||
ESP_LOGW(tag, "ADC using default Vref (no eFuse calibration available)");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -320,7 +306,7 @@ float readBoardInputVoltage(void) {
|
||||
// Convert raw ADC to voltage using calibration
|
||||
uint32_t voltage_mv;
|
||||
esp_adc_cal_characteristics_t adc_chars;
|
||||
esp_adc_cal_characterize(ADC_UNIT_1, ADC_ATTEN_DB_11, ADC_WIDTH_BIT_12, 1100, &adc_chars);
|
||||
esp_adc_cal_characterize(ADC_UNIT_1, ADC_ATTEN_DB_12, ADC_WIDTH_BIT_12, 1100, &adc_chars);
|
||||
voltage_mv = esp_adc_cal_raw_to_voltage(reading, &adc_chars);
|
||||
|
||||
// Voltage divider: R1 = 10k (series to input), R2 = 470 (to ground). Measurement is across R2.
|
||||
|
||||
@ -12,7 +12,7 @@ TI_TMP102_Compatible *tSensor = nullptr;
|
||||
void Init_TSensor(uint8_t addr, TSENSOR_SETTINGS *tsettings) {
|
||||
|
||||
if(tsettings != nullptr) {
|
||||
t_settings = tsettings; // Store pointer reference
|
||||
t_settings = tsettings; // Store pointer reference```
|
||||
ESP_LOGI(tag, "TSensor settings loaded: SP1=%.1f, SP2=%.1f, FP1=%.1f, FP2=%.1f, Hyst=%.1f",
|
||||
t_settings->setpoint1, t_settings->setpoint2,
|
||||
t_settings->fanPower1, t_settings->fanPower2, t_settings->hyst);
|
||||
|
||||
212
src/my_wifi.cpp
212
src/my_wifi.cpp
@ -806,8 +806,129 @@ void Setup_WebServer_Handlers(AsyncWebServer &server) {
|
||||
});
|
||||
}
|
||||
|
||||
void handleFilesUpload_OnBody(AsyncWebServerRequest *request, String filename, size_t index,
|
||||
uint8_t *data, size_t len, bool final) {
|
||||
// Hardened upload body handler: better path sanitization, robust write loop,
|
||||
// safe temp-path handling, and stricter size checks.
|
||||
void handleFilesUpload_OnBody(AsyncWebServerRequest *request, String filename, size_t index, uint8_t *data, size_t len, bool final) {
|
||||
static const size_t MAX_UPLOAD_SIZE = 1024 * 512; // 512KB limit
|
||||
|
||||
// Optional: require auth for uploads
|
||||
// if (!request->authenticate(http_username, http_password)) {
|
||||
// return request->requestAuthentication();
|
||||
// }
|
||||
|
||||
// Use only the basename of the provided filename to avoid client-supplied path components
|
||||
int lastSlash = max(filename.lastIndexOf('/'), filename.lastIndexOf('\\'));
|
||||
String safeFilename = (lastSlash >= 0) ? filename.substring(lastSlash + 1) : filename;
|
||||
if (safeFilename.length() == 0) {
|
||||
ESP_LOGE(tag, "Empty filename provided");
|
||||
request->send(400, "text/plain", "Invalid filename");
|
||||
return;
|
||||
}
|
||||
|
||||
if (index == 0) {
|
||||
// Initial upload chunk: validate dir param
|
||||
if (!request->hasParam("dir-path", true, false)) {
|
||||
ESP_LOGE(tag, "Missing dir-path parameter");
|
||||
request->send(400, "text/plain", "Missing dir-path");
|
||||
return;
|
||||
}
|
||||
AsyncWebParameter *p = request->getParam("dir-path", true, false);
|
||||
String dir = p->value();
|
||||
|
||||
// Basic sanitize of dir param
|
||||
if (dir.indexOf("..") >= 0) {
|
||||
ESP_LOGW(tag, "Rejected upload with unsafe dir-path: %s", dir.c_str());
|
||||
request->send(400, "text/plain", "Invalid upload path");
|
||||
return;
|
||||
}
|
||||
// Ensure leading slash and collapse duplicate slashes
|
||||
if (!dir.startsWith("/")) dir = "/" + dir;
|
||||
while (dir.indexOf("//") >= 0) dir.replace("//", "/");
|
||||
|
||||
// OPTIONAL: constrain to a base directory (uncomment to enforce)
|
||||
// const String allowedPrefix = "/www";
|
||||
// if (!dir.startsWith(allowedPrefix)) {
|
||||
// ESP_LOGW(tag, "Rejected upload outside allowed dir: %s", dir.c_str());
|
||||
// request->send(400, "text/plain", "Invalid upload directory");
|
||||
// return;
|
||||
// }
|
||||
|
||||
String path = dir;
|
||||
if (!path.endsWith("/")) path += "/";
|
||||
path += safeFilename;
|
||||
|
||||
// Final sanitize
|
||||
if (path.indexOf("..") >= 0) {
|
||||
ESP_LOGW(tag, "Rejected upload with unsafe path after combine: %s", path.c_str());
|
||||
request->send(400, "text/plain", "Invalid upload path");
|
||||
return;
|
||||
}
|
||||
while (path.indexOf("//") >= 0) path.replace("//", "/");
|
||||
|
||||
ESP_LOGI(tag, "Starting upload: %s", path.c_str());
|
||||
|
||||
// Open file for writing (truncate)
|
||||
request->_tempFile = LittleFS.open(path, "w");
|
||||
if (!request->_tempFile) {
|
||||
ESP_LOGE(tag, "Failed to create file: %s", path.c_str());
|
||||
request->send(500, "text/plain", "Failed to create file");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// If we have no file handle, abort
|
||||
if (!request->_tempFile) {
|
||||
ESP_LOGE(tag, "No temp file available for upload chunk");
|
||||
request->send(500, "text/plain", "Internal error");
|
||||
return;
|
||||
}
|
||||
|
||||
// Bounds check: protect against overflow and enforce max size
|
||||
if (index > MAX_UPLOAD_SIZE || len > MAX_UPLOAD_SIZE || index + len > MAX_UPLOAD_SIZE) {
|
||||
// Capture filename before closing
|
||||
String tmpName = request->_tempFile.name();
|
||||
request->_tempFile.close();
|
||||
LittleFS.remove(tmpName);
|
||||
ESP_LOGE(tag, "Upload too large or out of bounds: index=%u len=%u", (unsigned)index, (unsigned)len);
|
||||
request->send(413, "text/plain", "File too large");
|
||||
return;
|
||||
}
|
||||
|
||||
// Write chunk (handle partial writes)
|
||||
if (len > 0) {
|
||||
size_t toWrite = len;
|
||||
size_t writtenTotal = 0;
|
||||
const uint8_t *bufPtr = data;
|
||||
|
||||
while (toWrite > 0) {
|
||||
size_t written = request->_tempFile.write(bufPtr + writtenTotal, toWrite);
|
||||
if (written == 0) {
|
||||
// Attempt to flush/close and remove the file
|
||||
String tmpName = request->_tempFile.name();
|
||||
request->_tempFile.close();
|
||||
LittleFS.remove(tmpName);
|
||||
ESP_LOGE(tag, "Write failed after %u/%u bytes", (unsigned)writtenTotal, (unsigned)len);
|
||||
request->send(500, "text/plain", "Write failed");
|
||||
return;
|
||||
}
|
||||
writtenTotal += written;
|
||||
toWrite -= written;
|
||||
}
|
||||
}
|
||||
|
||||
if (final) {
|
||||
// Capture path/name for logging and for safe removal if needed
|
||||
String finalName = request->_tempFile.name();
|
||||
|
||||
request->_tempFile.close();
|
||||
|
||||
// Log final size if possible (index + len)
|
||||
ESP_LOGI(tag, "Upload complete: %s, %u bytes", safeFilename.c_str(), (unsigned)(index + len));
|
||||
request->redirect("/files");
|
||||
}
|
||||
}
|
||||
/*
|
||||
void handleFilesUpload_OnBody(AsyncWebServerRequest *request, String filename, size_t index, uint8_t *data, size_t len, bool final) {
|
||||
static const size_t MAX_UPLOAD_SIZE = 1024 * 512; // 512KB limit
|
||||
|
||||
if (!index) {
|
||||
@ -863,10 +984,10 @@ void handleFilesUpload_OnBody(AsyncWebServerRequest *request, String filename, s
|
||||
request->redirect("/files");
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
// Send html file with template processing {{VAR}}
|
||||
bool sendHtmlFile(const char *filePath, AsyncWebServerRequest *request,
|
||||
String (*callback)(const String &)) {
|
||||
bool sendHtmlFile(const char *filePath, AsyncWebServerRequest *request, String (*callback)(const String &)) {
|
||||
const char *htmlFile = readFile(LittleFS, filePath);
|
||||
if (!htmlFile) {
|
||||
ESP_LOGE(tag, "Failed to read file: %s", filePath);
|
||||
@ -877,7 +998,7 @@ bool sendHtmlFile(const char *filePath, AsyncWebServerRequest *request,
|
||||
String processedData = varReplace(htmlFile, callback);
|
||||
delete[] htmlFile; // Clean up allocated memory
|
||||
|
||||
ESP_LOGI(tag, "Sent file: %s", filePath);
|
||||
ESP_LOGD(tag, "Sent file: %s", filePath);
|
||||
request->send(200, "text/html", processedData);
|
||||
return true;
|
||||
}
|
||||
@ -1104,6 +1225,86 @@ void onWiFiEvent(WiFiEvent_t event) {
|
||||
}
|
||||
}
|
||||
|
||||
void Wifi_Start_MDNS(void) {
|
||||
// Validate mDnsName and build a safe fallback if needed
|
||||
String name = mDnsName;
|
||||
// Trim whitespace
|
||||
name.trim();
|
||||
// Fallback generation helper
|
||||
auto make_fallback = [&]() -> String {
|
||||
char macSuffix[5] = {0};
|
||||
uint8_t mac[6];
|
||||
WiFi.softAPmacAddress(mac);
|
||||
// take last two bytes as hex
|
||||
snprintf(macSuffix, sizeof(macSuffix), "%02X%02X", mac[4], mac[5]);
|
||||
String fh = "ata-" + String(macSuffix);
|
||||
return fh;
|
||||
};
|
||||
|
||||
if (name.length() == 0) {
|
||||
ESP_LOGW(tag, "mDnsName empty, generating fallback");
|
||||
name = make_fallback();
|
||||
}
|
||||
|
||||
// Trim to 63 chars
|
||||
if (name.length() > 63) {
|
||||
name = name.substring(0, 63);
|
||||
}
|
||||
|
||||
// Replace invalid characters with '-'
|
||||
for (size_t i = 0; i < name.length(); ++i) {
|
||||
char c = name[i];
|
||||
if (!((c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || (c >= 'A' && c <= 'Z') || c == '-')) {
|
||||
name[i] = '-';
|
||||
}
|
||||
}
|
||||
// Prevent leading/trailing hyphen
|
||||
if (name.startsWith("-")) name.remove(0, 1);
|
||||
if (name.endsWith("-")) name.remove(name.length() - 1, 1);
|
||||
if (name.length() == 0) {
|
||||
name = make_fallback();
|
||||
}
|
||||
|
||||
ESP_LOGI(tag, "Starting mDNS responder with name: %s", name.c_str());
|
||||
|
||||
// Ensure we have WiFi up when starting MDNS in STA mode
|
||||
if (WiFi.getMode() == WIFI_MODE_STA || WiFi.getMode() == WIFI_MODE_APSTA) {
|
||||
if (WiFi.localIP() == INADDR_NONE || WiFi.localIP().toString() == "0.0.0.0") {
|
||||
ESP_LOGW(tag, "No IP yet; MDNS may fail until network is up");
|
||||
// still attempt, but it's usually better to call this after station got IP
|
||||
}
|
||||
}
|
||||
|
||||
// Try to (re)start MDNS. If MDNS is already started we restart it to ensure name matches.
|
||||
// MDNS.end is safe to call even if not started.
|
||||
MDNS.end();
|
||||
|
||||
const int maxRetries = 2;
|
||||
bool started = false;
|
||||
for (int attempt = 0; attempt <= maxRetries && !started; ++attempt) {
|
||||
if (MDNS.begin(name.c_str())) {
|
||||
started = true;
|
||||
break;
|
||||
} else {
|
||||
ESP_LOGW(tag, "MDNS.begin() failed on attempt %d/%d", attempt + 1, maxRetries + 1);
|
||||
vTaskDelay(pdMS_TO_TICKS(200));
|
||||
}
|
||||
}
|
||||
|
||||
if (!started) {
|
||||
ESP_LOGE(tag, "Failed to start mDNS responder for %s", name.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
// Optionally advertise the HTTP service so discovery tools can find it
|
||||
MDNS.addService("http", "tcp", 80);
|
||||
|
||||
ESP_LOGI(tag, "mDNS responder started. Access via http://%s.local (may take a moment to appear)", name.c_str());
|
||||
|
||||
// Save the potentially-sanitized name back to global so other code can use it
|
||||
mDnsName = name;
|
||||
}
|
||||
/*
|
||||
void Wifi_Start_MDNS(void) {
|
||||
ESP_LOGV(tag, "Initializing MDNS: %s", mDnsName.c_str());
|
||||
if (!MDNS.begin(mDnsName.c_str())) {
|
||||
@ -1112,6 +1313,7 @@ void Wifi_Start_MDNS(void) {
|
||||
ESP_LOGV(tag, "You can access device via http://%s.local", mDnsName);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
bool writeFile(fs::FS &fs, const char *path, const char *message) {
|
||||
// Validate inputs
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user