40
40
#include "statistics_task.h"
41
41
#include "theme_api.h" // Add theme API include
42
42
#include "axe-os/api/system/asic_settings.h"
43
+ #include "display.h"
43
44
#include "http_server.h"
44
45
45
46
#define JSON_ALL_STATS_ELEMENT_SIZE 120
46
47
#define JSON_DASHBOARD_STATS_ELEMENT_SIZE 60
47
48
49
+ #define NVS_STR_LIMIT (4000 - 1)
50
+
48
51
#define ARRAY_SIZE (arr ) (sizeof(arr) / sizeof((arr)[0]))
49
52
50
53
static const char * TAG = "http_server" ;
@@ -54,8 +57,13 @@ typedef struct {
54
57
const char * name ;
55
58
int json_type ;
56
59
nvs_type_t nvs_type ;
60
+ int min ;
61
+ int max ;
57
62
const char * nvs_name ;
58
- } SettingsFormat ;
63
+ bool updated ;
64
+ int int_value ;
65
+ char * str_value ;
66
+ } Settings ;
59
67
60
68
/* Handler for WiFi scan endpoint */
61
69
static esp_err_t GET_wifi_scan (httpd_req_t * req )
@@ -462,113 +470,191 @@ bool check_json_type(int expected_type, const cJSON * const item)
462
470
return false;
463
471
}
464
472
465
- bool check_settings_and_update (const cJSON * const root , bool update )
473
+ Settings * getUpdatedSettings (const char * name , Settings settings [], uint32_t length )
474
+ {
475
+ if (name ) {
476
+ for (int i = 0 ; i < length ; i ++ ) {
477
+ if (settings [i ].updated && (strcmp (settings [i ].name , name ) == 0 )) {
478
+ return & settings [i ];
479
+ }
480
+ }
481
+ }
482
+ return NULL ;
483
+ }
484
+
485
+ bool check_settings_and_update (const cJSON * const root )
466
486
{
487
+ bool result = true;
467
488
const int cJSON_Option = (cJSON_Number | cJSON_True | cJSON_False );
468
489
469
- const SettingsFormat settings_format [] = {
470
- { .name = "stratumURL" , .json_type = cJSON_String , .nvs_type = NVS_TYPE_STR , .nvs_name = NVS_CONFIG_STRATUM_URL },
471
- { .name = "fallbackStratumURL" , .json_type = cJSON_String , .nvs_type = NVS_TYPE_STR , .nvs_name = NVS_CONFIG_FALLBACK_STRATUM_URL },
472
- { .name = "stratumUser" , .json_type = cJSON_String , .nvs_type = NVS_TYPE_STR , .nvs_name = NVS_CONFIG_STRATUM_USER },
473
- { .name = "stratumPassword" , .json_type = cJSON_String , .nvs_type = NVS_TYPE_STR , .nvs_name = NVS_CONFIG_STRATUM_PASS },
474
- { .name = "fallbackStratumUser" , .json_type = cJSON_String , .nvs_type = NVS_TYPE_STR , .nvs_name = NVS_CONFIG_FALLBACK_STRATUM_USER },
475
- { .name = "fallbackStratumPassword" , .json_type = cJSON_String , .nvs_type = NVS_TYPE_STR , .nvs_name = NVS_CONFIG_FALLBACK_STRATUM_PASS },
476
- { .name = "stratumPort" , .json_type = cJSON_Number , .nvs_type = NVS_TYPE_U16 , .nvs_name = NVS_CONFIG_STRATUM_PORT },
477
- { .name = "fallbackStratumPort" , .json_type = cJSON_Number , .nvs_type = NVS_TYPE_U16 , .nvs_name = NVS_CONFIG_FALLBACK_STRATUM_PORT },
478
- { .name = "ssid" , .json_type = cJSON_String , .nvs_type = NVS_TYPE_STR , .nvs_name = NVS_CONFIG_WIFI_SSID },
479
- { .name = "wifiPass" , .json_type = cJSON_String , .nvs_type = NVS_TYPE_STR , .nvs_name = NVS_CONFIG_WIFI_PASS },
480
- { .name = "hostname" , .json_type = cJSON_String , .nvs_type = NVS_TYPE_STR , .nvs_name = NVS_CONFIG_HOSTNAME },
481
- { .name = "coreVoltage" , .json_type = cJSON_Number , .nvs_type = NVS_TYPE_U16 , .nvs_name = NVS_CONFIG_ASIC_VOLTAGE },
482
- { .name = "frequency" , .json_type = cJSON_Number , .nvs_type = NVS_TYPE_U16 , .nvs_name = NVS_CONFIG_ASIC_FREQ },
483
- { .name = "overheat_mode" , .json_type = cJSON_Number , .nvs_type = NVS_TYPE_U16 , .nvs_name = NVS_CONFIG_OVERHEAT_MODE },
484
- { .name = "display" , .json_type = cJSON_String , .nvs_type = NVS_TYPE_STR , .nvs_name = NVS_CONFIG_DISPLAY },
485
- { .name = "rotation" , .json_type = cJSON_Number , .nvs_type = NVS_TYPE_U16 , .nvs_name = NVS_CONFIG_ROTATION },
486
- { .name = "invertscreen" , .json_type = cJSON_Option , .nvs_type = NVS_TYPE_U16 , .nvs_name = NVS_CONFIG_INVERT_SCREEN },
487
- { .name = "displayTimeout" , .json_type = cJSON_Number , .nvs_type = NVS_TYPE_I32 , .nvs_name = NVS_CONFIG_DISPLAY_TIMEOUT },
488
- { .name = "autofanspeed" , .json_type = cJSON_Option , .nvs_type = NVS_TYPE_U16 , .nvs_name = NVS_CONFIG_AUTO_FAN_SPEED },
489
- { .name = "fanspeed" , .json_type = cJSON_Number , .nvs_type = NVS_TYPE_U16 , .nvs_name = NVS_CONFIG_FAN_SPEED },
490
- { .name = "temptarget" , .json_type = cJSON_Number , .nvs_type = NVS_TYPE_U16 , .nvs_name = NVS_CONFIG_TEMP_TARGET },
491
- { .name = "statsFrequency" , .json_type = cJSON_Number , .nvs_type = NVS_TYPE_U16 , .nvs_name = NVS_CONFIG_STATISTICS_FREQUENCY },
492
- { .name = "overclockEnabled" , .json_type = cJSON_Option , .nvs_type = NVS_TYPE_U16 , .nvs_name = NVS_CONFIG_OVERCLOCK_ENABLED }
490
+ Settings settings [] = {
491
+ { .name = "stratumURL" , .json_type = cJSON_String , .nvs_type = NVS_TYPE_STR , .min = 0 , . max = NVS_STR_LIMIT , . nvs_name = NVS_CONFIG_STRATUM_URL },
492
+ { .name = "fallbackStratumURL" , .json_type = cJSON_String , .nvs_type = NVS_TYPE_STR , .min = 0 , . max = NVS_STR_LIMIT , . nvs_name = NVS_CONFIG_FALLBACK_STRATUM_URL },
493
+ { .name = "stratumUser" , .json_type = cJSON_String , .nvs_type = NVS_TYPE_STR , .min = 0 , . max = NVS_STR_LIMIT , . nvs_name = NVS_CONFIG_STRATUM_USER },
494
+ { .name = "stratumPassword" , .json_type = cJSON_String , .nvs_type = NVS_TYPE_STR , .min = 0 , . max = NVS_STR_LIMIT , . nvs_name = NVS_CONFIG_STRATUM_PASS },
495
+ { .name = "fallbackStratumUser" , .json_type = cJSON_String , .nvs_type = NVS_TYPE_STR , .min = 0 , . max = NVS_STR_LIMIT , . nvs_name = NVS_CONFIG_FALLBACK_STRATUM_USER },
496
+ { .name = "fallbackStratumPassword" , .json_type = cJSON_String , .nvs_type = NVS_TYPE_STR , .min = 0 , . max = NVS_STR_LIMIT , . nvs_name = NVS_CONFIG_FALLBACK_STRATUM_PASS },
497
+ { .name = "stratumPort" , .json_type = cJSON_Number , .nvs_type = NVS_TYPE_U16 , .min = 0 , . max = USHRT_MAX , . nvs_name = NVS_CONFIG_STRATUM_PORT },
498
+ { .name = "fallbackStratumPort" , .json_type = cJSON_Number , .nvs_type = NVS_TYPE_U16 , .min = 0 , . max = USHRT_MAX , . nvs_name = NVS_CONFIG_FALLBACK_STRATUM_PORT },
499
+ { .name = "ssid" , .json_type = cJSON_String , .nvs_type = NVS_TYPE_STR , .min = 1 , . max = 32 , . nvs_name = NVS_CONFIG_WIFI_SSID },
500
+ { .name = "wifiPass" , .json_type = cJSON_String , .nvs_type = NVS_TYPE_STR , .min = 1 , . max = 63 , . nvs_name = NVS_CONFIG_WIFI_PASS },
501
+ { .name = "hostname" , .json_type = cJSON_String , .nvs_type = NVS_TYPE_STR , .min = 1 , . max = 32 , . nvs_name = NVS_CONFIG_HOSTNAME },
502
+ { .name = "coreVoltage" , .json_type = cJSON_Number , .nvs_type = NVS_TYPE_U16 , .min = 1 , . max = USHRT_MAX , . nvs_name = NVS_CONFIG_ASIC_VOLTAGE },
503
+ { .name = "frequency" , .json_type = cJSON_Number , .nvs_type = NVS_TYPE_U16 , .min = 1 , . max = USHRT_MAX , . nvs_name = NVS_CONFIG_ASIC_FREQ },
504
+ { .name = "overheat_mode" , .json_type = cJSON_Number , .nvs_type = NVS_TYPE_U16 , .min = 0 , . max = 0 , . nvs_name = NVS_CONFIG_OVERHEAT_MODE },
505
+ { .name = "display" , .json_type = cJSON_String , .nvs_type = NVS_TYPE_STR , .min = 0 , . max = NVS_STR_LIMIT , . nvs_name = NVS_CONFIG_DISPLAY },
506
+ { .name = "rotation" , .json_type = cJSON_Number , .nvs_type = NVS_TYPE_U16 , .min = 0 , . max = 270 , . nvs_name = NVS_CONFIG_ROTATION },
507
+ { .name = "invertscreen" , .json_type = cJSON_Option , .nvs_type = NVS_TYPE_U16 , .min = 0 , . max = 1 , . nvs_name = NVS_CONFIG_INVERT_SCREEN },
508
+ { .name = "displayTimeout" , .json_type = cJSON_Number , .nvs_type = NVS_TYPE_I32 , .min = -1 , . max = USHRT_MAX , . nvs_name = NVS_CONFIG_DISPLAY_TIMEOUT },
509
+ { .name = "autofanspeed" , .json_type = cJSON_Option , .nvs_type = NVS_TYPE_U16 , .min = 0 , . max = 1 , . nvs_name = NVS_CONFIG_AUTO_FAN_SPEED },
510
+ { .name = "fanspeed" , .json_type = cJSON_Number , .nvs_type = NVS_TYPE_U16 , .min = 0 , . max = 100 , . nvs_name = NVS_CONFIG_FAN_SPEED },
511
+ { .name = "temptarget" , .json_type = cJSON_Number , .nvs_type = NVS_TYPE_U16 , .min = 35 , . max = 66 , . nvs_name = NVS_CONFIG_TEMP_TARGET },
512
+ { .name = "statsFrequency" , .json_type = cJSON_Number , .nvs_type = NVS_TYPE_U16 , .min = 0 , . max = USHRT_MAX , . nvs_name = NVS_CONFIG_STATISTICS_FREQUENCY },
513
+ { .name = "overclockEnabled" , .json_type = cJSON_Option , .nvs_type = NVS_TYPE_U16 , .min = 0 , . max = 1 , . nvs_name = NVS_CONFIG_OVERCLOCK_ENABLED }
493
514
};
494
515
495
- for (int i = 0 ; i < ARRAY_SIZE (settings_format ); i ++ ) {
496
- cJSON * item = cJSON_GetObjectItem (root , settings_format [i ].name );
516
+ // check for data type and data type range
517
+ for (int i = 0 ; i < ARRAY_SIZE (settings ); i ++ ) {
518
+ cJSON * item = cJSON_GetObjectItem (root , settings [i ].name );
497
519
if (item ) {
498
- if (check_json_type (settings_format [i ].json_type , item )) {
499
- switch (settings_format [i ].nvs_type ) {
520
+ // check data type
521
+ if (check_json_type (settings [i ].json_type , item )) {
522
+ // check data type range
523
+ switch (settings [i ].nvs_type ) {
500
524
case NVS_TYPE_U8 :
501
525
if ((0 > item -> valueint ) || (UCHAR_MAX < item -> valueint )) {
502
- ESP_LOGW (TAG , "Value '%d' for '%s' is not compatible with NVS_TYPE_U8" , item -> valueint , settings_format [i ].name );
503
- return false;
504
- }
505
- if (update ) {
506
- nvs_config_set_u16 (settings_format [i ].nvs_name , item -> valueint ); // nvs u8 is not used
526
+ ESP_LOGW (TAG , "Value '%d' for '%s' is not compatible with NVS_TYPE_U8" , item -> valueint , settings [i ].name );
527
+ result = false;
507
528
}
508
529
break ;
509
530
case NVS_TYPE_U16 :
510
531
if ((0 > item -> valueint ) || (USHRT_MAX < item -> valueint )) {
511
- ESP_LOGW (TAG , "Value '%d' for '%s' is not compatible with NVS_TYPE_U16" , item -> valueint , settings_format [i ].name );
512
- return false;
513
- }
514
- if (update ) {
515
- nvs_config_set_u16 (settings_format [i ].nvs_name , item -> valueint );
532
+ ESP_LOGW (TAG , "Value '%d' for '%s' is not compatible with NVS_TYPE_U16" , item -> valueint , settings [i ].name );
533
+ result = false;
516
534
}
517
535
break ;
518
536
case NVS_TYPE_U32 :
519
537
if (0 > item -> valueint ) {
520
- ESP_LOGW (TAG , "Value '%d' for '%s' is not compatible with NVS_TYPE_U32" , item -> valueint , settings_format [i ].name );
521
- return false;
522
- }
523
- if (update ) {
524
- nvs_config_set_u64 (settings_format [i ].nvs_name , item -> valueint ); // nvs u32 is not used
538
+ ESP_LOGW (TAG , "Value '%d' for '%s' is not compatible with NVS_TYPE_U32" , item -> valueint , settings [i ].name );
539
+ result = false;
525
540
}
526
541
break ;
527
542
case NVS_TYPE_I8 :
528
543
if ((CHAR_MIN > item -> valueint ) || (CHAR_MAX < item -> valueint )) {
529
- ESP_LOGW (TAG , "Value '%d' for '%s' is not compatible with NVS_TYPE_I8" , item -> valueint , settings_format [i ].name );
530
- return false;
531
- }
532
- if (update ) {
533
- nvs_config_set_i32 (settings_format [i ].nvs_name , item -> valueint ); // nvs i8 is not used
544
+ ESP_LOGW (TAG , "Value '%d' for '%s' is not compatible with NVS_TYPE_I8" , item -> valueint , settings [i ].name );
545
+ result = false;
534
546
}
535
547
break ;
536
548
case NVS_TYPE_I16 :
537
549
if ((SHRT_MIN > item -> valueint ) || (SHRT_MAX < item -> valueint )) {
538
- ESP_LOGW (TAG , "Value '%d' for '%s' is not compatible with NVS_TYPE_I16" , item -> valueint , settings_format [i ].name );
539
- return false;
540
- }
541
- if (update ) {
542
- nvs_config_set_i32 (settings_format [i ].nvs_name , item -> valueint ); // nvs i16 is not used
550
+ ESP_LOGW (TAG , "Value '%d' for '%s' is not compatible with NVS_TYPE_I16" , item -> valueint , settings [i ].name );
551
+ result = false;
543
552
}
544
553
break ;
545
554
case NVS_TYPE_I32 :
546
- if (update ) {
547
- nvs_config_set_i32 (settings_format [i ].nvs_name , item -> valueint );
548
- }
549
555
break ;
550
556
case NVS_TYPE_STR :
551
- if (update ) {
552
- nvs_config_set_string (settings_format [i ].nvs_name , item -> valuestring );
557
+ const size_t str_value_len = strlen (item -> valuestring );
558
+ settings [i ].str_value = strdup (item -> valuestring );
559
+
560
+ if (0 > settings [i ].min ) {
561
+ settings [i ].min = 0 ;
562
+ }
563
+
564
+ if ((str_value_len < settings [i ].min ) || (str_value_len > settings [i ].max )) {
565
+ ESP_LOGW (TAG , "Value '%s' for '%s' is out of length (%d-%d)" , item -> valuestring , settings [i ].name , settings [i ].min , settings [i ].max );
566
+ result = false;
553
567
}
554
568
break ;
555
569
default :
556
- ESP_LOGW (TAG , "NVS type (%d) for '%s' not supported" , settings_format [i ].nvs_type , settings_format [i ].name );
557
- return false;
570
+ ESP_LOGW (TAG , "NVS type (%d) for '%s' not supported" , settings [i ].nvs_type , settings [i ].name );
571
+ result = false;
572
+ break ;
558
573
}
574
+
575
+ // check value range
576
+ if (NVS_TYPE_STR != settings [i ].nvs_type ) {
577
+ if ((settings [i ].min > item -> valueint ) || (settings [i ].max < item -> valueint )) {
578
+ ESP_LOGW (TAG , "Value '%d' for '%s' is out of range (%d-%d)" , item -> valueint , settings [i ].name , settings [i ].min , settings [i ].max );
579
+ result = false;
580
+ }
581
+ }
582
+
583
+ // mark for update
584
+ settings [i ].int_value = item -> valueint ;
585
+ settings [i ].updated = true;
559
586
} else {
560
- ESP_LOGW (TAG , "Expected JSON type (%d) for setting '%s'" , settings_format [i ].json_type , settings_format [i ].name );
561
- return false;
587
+ ESP_LOGW (TAG , "Expected JSON type (%d) for setting '%s'" , settings [i ].json_type , settings [i ].name );
588
+ result = false;
589
+ }
590
+ }
591
+ }
592
+
593
+ // check individual values
594
+ if (result ) {
595
+ Settings * updatedSettings = getUpdatedSettings ("display" , settings , ARRAY_SIZE (settings ));
596
+ if (updatedSettings ) {
597
+ if (NULL == get_display_config (updatedSettings -> str_value )) {
598
+ ESP_LOGW (TAG , "Display config '%s' for '%s' is not available" , updatedSettings -> str_value , updatedSettings -> name );
599
+ result = false;
600
+ }
601
+ }
602
+
603
+ updatedSettings = getUpdatedSettings ("rotation" , settings , ARRAY_SIZE (settings ));
604
+ if (updatedSettings ) {
605
+ switch (updatedSettings -> int_value ) {
606
+ case 0 : case 90 : case 180 : case 270 :
607
+ break ;
608
+ default :
609
+ ESP_LOGW (TAG , "Value '%d' for '%s' is not possible" , updatedSettings -> int_value , updatedSettings -> name );
610
+ result = false;
611
+ break ;
612
+ }
613
+ }
614
+ }
615
+
616
+ // update NVS (if result is okay) and clean up
617
+ for (int i = 0 ; i < ARRAY_SIZE (settings ); i ++ ) {
618
+ if (settings [i ].updated ) {
619
+ if (result ) {
620
+ switch (settings [i ].nvs_type ) {
621
+ case NVS_TYPE_U8 :
622
+ nvs_config_set_u16 (settings [i ].nvs_name , (uint16_t )settings [i ].int_value ); // nvs u8 is not used
623
+ break ;
624
+ case NVS_TYPE_U16 :
625
+ nvs_config_set_u16 (settings [i ].nvs_name , (uint16_t )settings [i ].int_value );
626
+ break ;
627
+ case NVS_TYPE_U32 :
628
+ nvs_config_set_u64 (settings [i ].nvs_name , (uint64_t )settings [i ].int_value ); // nvs u32 is not used
629
+ break ;
630
+ case NVS_TYPE_I8 :
631
+ nvs_config_set_i32 (settings [i ].nvs_name , settings [i ].int_value ); // nvs i8 is not used
632
+ break ;
633
+ case NVS_TYPE_I16 :
634
+ nvs_config_set_i32 (settings [i ].nvs_name , settings [i ].int_value ); // nvs i16 is not used
635
+ break ;
636
+ case NVS_TYPE_I32 :
637
+ nvs_config_set_i32 (settings [i ].nvs_name , settings [i ].int_value );
638
+ break ;
639
+ case NVS_TYPE_STR :
640
+ nvs_config_set_string (settings [i ].nvs_name , settings [i ].str_value );
641
+ break ;
642
+ default :
643
+ break ;
644
+ }
645
+ }
646
+
647
+ if (NVS_TYPE_STR == settings [i ].nvs_type ) {
648
+ free (settings [i ].str_value );
562
649
}
563
650
}
564
651
}
565
652
566
- return true ;
653
+ return result ;
567
654
}
568
655
569
656
static esp_err_t PATCH_update_settings (httpd_req_t * req )
570
657
{
571
-
572
658
if (is_network_allowed (req ) != ESP_OK ) {
573
659
return httpd_resp_send_err (req , HTTPD_401_UNAUTHORIZED , "Unauthorized" );
574
660
}
@@ -605,9 +691,7 @@ static esp_err_t PATCH_update_settings(httpd_req_t * req)
605
691
return ESP_OK ;
606
692
}
607
693
608
- if (check_settings_and_update (root , false)) {
609
- check_settings_and_update (root , true);
610
- } else {
694
+ if (!check_settings_and_update (root )) {
611
695
cJSON_Delete (root );
612
696
httpd_resp_send_err (req , HTTPD_400_BAD_REQUEST , "Wrong API input" );
613
697
return ESP_OK ;
0 commit comments