#ifndef _SANITYCHECK_H_ #define _SANITYCHECK_H_ // Utility macros for handling quotes #define Q(x) #x #define QUOTE(x) Q(x) // Utility macros for checking string lengths #define STRING_LENGTH_CHECK(str, max_length) (sizeof(str) <= (max_length) + 1) #define IS_ALPHANUMERIC(c) ((((c) >= '0') && ((c) <= '9')) || (((c) >= 'A') && ((c) <= 'Z')) || (((c) >= 'a') && ((c) <= 'z'))) #define IS_PRINTABLE_ASCII(c) ((c) >= 32 && (c) <= 126) #define IS_VALID_WIFI_CHAR(c) (IS_PRINTABLE_ASCII(c)) #define IS_ALPHANUMERIC_HELPER(str, i) (i >= sizeof(str) - 1 || IS_ALPHANUMERIC(str[i])) #define IS_PRINTABLE_ASCII_HELPER(str, i) (i >= sizeof(str) - 1 || IS_PRINTABLE_ASCII(str[i])) #define IS_VALID_WIFI_CHAR_HELPER(str, i) (i >= sizeof(str) - 1 || IS_VALID_WIFI_CHAR(str[i])) #define IS_ALPHANUMERIC_IMPL(str, i) (IS_ALPHANUMERIC_HELPER(str, i) && IS_ALPHANUMERIC_HELPER(str, i+1) && IS_ALPHANUMERIC_HELPER(str, i+2) && IS_ALPHANUMERIC_HELPER(str, i+3) && IS_ALPHANUMERIC_HELPER(str, i+4) && IS_ALPHANUMERIC_HELPER(str, i+5) && IS_ALPHANUMERIC_HELPER(str, i+6) && IS_ALPHANUMERIC_HELPER(str, i+7) && IS_ALPHANUMERIC_HELPER(str, i+8) && IS_ALPHANUMERIC_HELPER(str, i+9) && IS_ALPHANUMERIC_HELPER(str, i+10) && IS_ALPHANUMERIC_HELPER(str, i+11) && IS_ALPHANUMERIC_HELPER(str, i+12) && IS_ALPHANUMERIC_HELPER(str, i+13) && IS_ALPHANUMERIC_HELPER(str, i+14) && IS_ALPHANUMERIC_HELPER(str, i+15) && IS_ALPHANUMERIC_HELPER(str, i+16)) #define IS_PRINTABLE_ASCII_IMPL(str, i) (IS_PRINTABLE_ASCII_HELPER(str, i) && IS_PRINTABLE_ASCII_HELPER(str, i+1) && IS_PRINTABLE_ASCII_HELPER(str, i+2) && IS_PRINTABLE_ASCII_HELPER(str, i+3) && IS_PRINTABLE_ASCII_HELPER(str, i+4) && IS_PRINTABLE_ASCII_HELPER(str, i+5) && IS_PRINTABLE_ASCII_HELPER(str, i+6) && IS_PRINTABLE_ASCII_HELPER(str, i+7) && IS_PRINTABLE_ASCII_HELPER(str, i+8) && IS_PRINTABLE_ASCII_HELPER(str, i+9) && IS_PRINTABLE_ASCII_HELPER(str, i+10) && IS_PRINTABLE_ASCII_HELPER(str, i+11) && IS_PRINTABLE_ASCII_HELPER(str, i+12) && IS_PRINTABLE_ASCII_HELPER(str, i+13) && IS_PRINTABLE_ASCII_HELPER(str, i+14) && IS_PRINTABLE_ASCII_HELPER(str, i+15) && IS_PRINTABLE_ASCII_HELPER(str, i+16) && IS_PRINTABLE_ASCII_HELPER(str, i+17) && IS_PRINTABLE_ASCII_HELPER(str, i+18) && IS_PRINTABLE_ASCII_HELPER(str, i+19) && IS_PRINTABLE_ASCII_HELPER(str, i+20) && IS_PRINTABLE_ASCII_HELPER(str, i+21) && IS_PRINTABLE_ASCII_HELPER(str, i+22) && IS_PRINTABLE_ASCII_HELPER(str, i+23) && IS_PRINTABLE_ASCII_HELPER(str, i+24)) #define IS_ALPHANUMERIC_STRING(str) (IS_ALPHANUMERIC_IMPL(str, 0)) #define IS_PRINTABLE_ASCII_STRING(str) (IS_PRINTABLE_ASCII_IMPL(str, 0)) #define IS_VALID_WIFI_STRING(str) (IS_VALID_WIFI_CHAR_HELPER(str, 0) && IS_VALID_WIFI_CHAR_HELPER(str, 1) && IS_VALID_WIFI_CHAR_HELPER(str, 2) && IS_VALID_WIFI_CHAR_HELPER(str, 3) && IS_VALID_WIFI_CHAR_HELPER(str, 4) && IS_VALID_WIFI_CHAR_HELPER(str, 5) && IS_VALID_WIFI_CHAR_HELPER(str, 6) && IS_VALID_WIFI_CHAR_HELPER(str, 7) && IS_VALID_WIFI_CHAR_HELPER(str, 8) && IS_VALID_WIFI_CHAR_HELPER(str, 9) && IS_VALID_WIFI_CHAR_HELPER(str, 10) && IS_VALID_WIFI_CHAR_HELPER(str, 11) && IS_VALID_WIFI_CHAR_HELPER(str, 12) && IS_VALID_WIFI_CHAR_HELPER(str, 13) && IS_VALID_WIFI_CHAR_HELPER(str, 14) && IS_VALID_WIFI_CHAR_HELPER(str, 15) && IS_VALID_WIFI_CHAR_HELPER(str, 16) && IS_VALID_WIFI_CHAR_HELPER(str, 17) && IS_VALID_WIFI_CHAR_HELPER(str, 18) && IS_VALID_WIFI_CHAR_HELPER(str, 19) && IS_VALID_WIFI_CHAR_HELPER(str, 20) && IS_VALID_WIFI_CHAR_HELPER(str, 21) && IS_VALID_WIFI_CHAR_HELPER(str, 22) && IS_VALID_WIFI_CHAR_HELPER(str, 23) && IS_VALID_WIFI_CHAR_HELPER(str, 24) && IS_VALID_WIFI_CHAR_HELPER(str, 25) && IS_VALID_WIFI_CHAR_HELPER(str, 26) && IS_VALID_WIFI_CHAR_HELPER(str, 27) && IS_VALID_WIFI_CHAR_HELPER(str, 28) && IS_VALID_WIFI_CHAR_HELPER(str, 29) && IS_VALID_WIFI_CHAR_HELPER(str, 30) && IS_VALID_WIFI_CHAR_HELPER(str, 31) && IS_VALID_WIFI_CHAR_HELPER(str, 32)) // ADMIN_PASSWORD check #ifndef ADMIN_PASSWORD #error "You need to define ADMIN_PASSWORD for OTA-Update" #else _Static_assert(STRING_LENGTH_CHECK(QUOTE(ADMIN_PASSWORD), 16), "ADMIN_PASSWORD must be at most 16 characters long"); #endif // WIFI_AP_SSID check #ifndef WIFI_AP_SSID #warning "No WIFI_AP_SSID defined. Using DeviceName" #define WIFI_AP_SSID DEVICE_NAME #else _Static_assert(STRING_LENGTH_CHECK(QUOTE(WIFI_AP_SSID), 32), "WIFI_AP_SSID must be at most 32 characters long"); _Static_assert(IS_VALID_WIFI_STRING(QUOTE(WIFI_AP_SSID)), "WIFI_AP_SSID must contain only valid WiFi characters"); #endif // WIFI_PASS_SEED check #ifndef WIFI_PASS_SEED #error "You must define an WIFI_PASS_SEED for Standalone AP-Mode" #else _Static_assert(STRING_LENGTH_CHECK(QUOTE(WIFI_PASS_SEED), 16), "WIFI_PASS_SEED must be at most 16 characters long"); _Static_assert(IS_ALPHANUMERIC_STRING(QUOTE(WIFI_PASS_SEED)), "WIFI_PASS_SEED must contain only alphanumeric characters (a-z, A-Z, 0-9)"); #endif // DEVICE_NAME check #ifndef DEVICE_NAME #error "You must define DEVICE_NAME" #else _Static_assert(STRING_LENGTH_CHECK(QUOTE(DEVICE_NAME), 24), "DEVICE_NAME must be at most 24 characters long"); _Static_assert(IS_VALID_WIFI_STRING(QUOTE(DEVICE_NAME)), "DEVICE_NAME must contain only valid WiFi characters"); #endif // Mutual exclusion check for LoRa features #if defined(FEATURE_ENABLE_UARTLORA) && defined(FEATURE_ENABLE_LORA) #error "You cannot enable LoRa and UART-Protocol at the same time!" #endif // WIFI_CLIENT checks #ifdef FEATURE_ENABLE_WIFI_CLIENT #ifndef WIFI_PASSWORD_CLIENT #error "You must define an WIFI_PASSWORD_CLIENT for OTA-Update" #else _Static_assert(STRING_LENGTH_CHECK(QUOTE(WIFI_PASSWORD_CLIENT), 63), "WIFI_PASSWORD_CLIENT must be at most 63 characters long"); #endif #ifndef WIFI_SSID_CLIENT #error "You must define an WIFI_SSID_CLIENT for OTA-Update" #else _Static_assert(STRING_LENGTH_CHECK(QUOTE(WIFI_SSID_CLIENT), 32), "WIFI_SSID_CLIENT must be at most 32 characters long"); _Static_assert(IS_VALID_WIFI_STRING(QUOTE(WIFI_SSID_CLIENT)), "WIFI_SSID_CLIENT must contain only valid WiFi characters"); #endif #endif #endif // _SANITYCHECK_H_