Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Make variable have same type/effect as #define?

I'm setting up a wifi connection between an ESP32 and a router. The ESP32 has a struct that holds all of the wifi config details, two of which are the SSID and password. I am having trouble setting these two if I try to use a variable.

It works if I define the strings I want using #define....sta is the struct that holds the configuration parameters, sta is unioned with another struct into the data type that is wifi_config_t....ssid and password are of type uint8_t

//These work
#define ESP_SSID "AccessPoint"
#define ESP_PASS "Pass" 

//These don't work
char ESP_SSID[32] = "AccessPoint" //32 since that's max SSID length
char ESP_PASS[64] = "Pass" //64 since that's max pass length

//...later in code...
wifi_config_t wifi_config = {
    .sta = {
        .ssid = ESP_SSID,
        .password = ESP_PASS
    },
};

//...definition of .sta ...
typedef struct {
    uint8_t ssid[32];
    uint8_t password[64];
...
} wifi_sta_config_t;

But I am trying to make it so that I can change the SSID and Pass at run time, which is why I want to set up a variable. However, if I use the variable versions it causes these errors:

warning: initialization makes integer from pointer without a cast [-Wint-conversion]
.ssid = ESP_SSID,
        ^
warning: initialization makes integer from pointer without a cast [-Wint-conversion]
.password = ESP_PASS
            ^
error:missing braces around initializer [-Werror=missing-braces]
.sta = {
       ^

I am aware that this is a type miss match but I can't for the life of me figure out how to make the variable version have the same effect as the #define version!

like image 715
phantomBlurrr Avatar asked Mar 03 '23 19:03

phantomBlurrr


1 Answers

Array initialization

The reason your code fails to compile is that the ssid element in the wifi_config_sta_t struct is an array type - and arrays can only be initialized from either a string literal or a brace-enclosed list. See here for explanation. You are trying to initialize it from another array variable - which is illegal.

The following initializations, for example, are legal.

char ssid1[32] = "My WiFi"; // from string literal -> okay
 // from brace-enclosed list -> okay
char ssid2[32] = {'M', 'y', ' ', 'W', 'i', 'F', 'i'};

This, on the other hand, is not:

char ESP_SSID[32] = "My WiFi";
// won't work - ESP_SSID is not a string literal
char ssid[32] = ESP_SSID; // ILLEGAL

because ESP_SSID is not a constant expression.

This answer to a similar question on SO gives further examples.

Preprocessor and constant expressions

Note that

#define ESP_SSID "AccessPoint"
// etc.
char ssid[32] = ESP_SSID;

is the same as

char ssid[32] = "AccessPoint";

I.e., any instances within the code of ESP_SSID are replaced with the string literal "AccessPoint" during the pre-processing stage. That's why using a #define works for your application - you are just initializing the array using a string literal.

Array assignment

If you want to update the SSID and password during run-time, one option is to zero-initialize the array on startup - and then use strcpy() to update the values as needed.

wifi_config_t wifi_config = {0}; // Zero initialize all struct memberes
strcpy((char *)wifi_config.sta.ssid, ESP_SSID);
strcpy((char *)wifi_config.sta.password, ESP_PASS);

Note that it is necessary to cast the uint8_t * to char *, due to the compilation options used in the ESP IDF build process.

like image 128
David Collins Avatar answered Mar 18 '23 09:03

David Collins