Assigning the value of a const char *

I have four states I want to control and have created

const char *   FANHUM = "0";
const char *   FANTIMED = "1";
const char *   FANONMAX = "2";
const char *   FANOFF = "3";

I want to set the variable I measure to a default state, so I've tried

char FANSTATE = FANHUM; but the compiler says:

error: invalid conversion from 'const char*' to 'char*' [-fpermissive]
   29 | char * FANSTATE = FANHUM;
      |                   ^~~~~~
      |                   |
      |                   const char*

What do I need to do to correct my mistake?

I would use integer values for the state variable, rather than character strings.

Then, unlike with character strings, the state values can be used very simply in if statements, switch case statements, etc.

Or use enums.

Thanks,
I started with integers but I'll need to compare them with MQTT message payloads which are (from memory) char *. When I used integers, I had a Switch Case to take action depending on which detected state but I couldn't find a way to convert the payload to an int, even though it's a single integer character. I don't mind either way, so long as I can get compatible types to assign and test

A pointer to some zero to hero well drafted docs on type management would be good. Searching has returned too many snarky comments or 'not quite what I'm after' on Stack Overflow and the like
Cheers

I don't know enums. I'll take a look

You can also use a char.

char FANHUM = '0'; // Single quotes

This is different from what you currently have... which is a pointer to a char array (char array because you use double quotes). So "0" is actually 2 bytes, because is includes a string terminator (0x00).

That is a pointer to a character or character array element.

Don't confuse that with a character string, which is a zero-terminated character array.

It would be sensible to assign integer state values to MQTT message payloads representing distinct states.

In this case, FANSTATE should be declared as const char *, because it points to a constant. This does not make FANSTATE itself constant, that would be declared as const char * const FANSTATE.

Thanks David_2018 I tried this and it compiled
const char * FANSTATE = FANHUM;

but when I tested it by adding
const char * FANSTATE = FANTIMED; // From prev. declaration: const char * FANTIMED = "1";

it failed with

/home/greg/Arduino/BathroomHumiditySensorSHT30/bathroomSHT30-esp8266MQTTClientv5/bathroomSHT30-esp8266MQTTClientv5.ino:31:14: error: redefinition of 'const char* FANSTATE'
   31 | const char * FANSTATE = FANTIMED;
      |              ^~~~~~~~
/home/greg/Arduino/BathroomHumiditySensorSHT30/bathroomSHT30-esp8266MQTTClientv5/bathroomSHT30-esp8266MQTTClientv5.ino:29:14: note: 'const char* FANSTATE' previously declared here
   29 | const char * FANSTATE = FANHUM;
      |              ^~~~~~~~

Which looks like it IS a const!?

Why make things hard for yourself... use a char... not a pointer. See post #6

Working myway through the answers - just happened to start at the bottom :stuck_out_tongue_winking_eye:

red_car. A couple of things:

  1. I've declared the state values as const chars as I want them to be constants (changed to single quotes)
const char  FANHUM    = '0';
const char  FANTIMED  = '1';
const char  FANONMAX  = '2';
const char  FANOFF    = '3';
  1. I declare FANSTATE as a char but not a constant and assign one of the above consts to it:
char FANSTATE = FANHUM;
  1. I try to assign one of the other consts to it:
char FANSTATE = FANTIMED;

And get a whole heap of errors, including the first,. which complains about redefinition of 'char FANSTATE'. Which looks wrong, if I've removed const from FANSTATE.

try

const char FANSTATE = FANHUM;

but integer enums might be better or simple chars

Sounds like you are putting "char" before FANSTATE every time you use it, which is attempting to create a new variable each time. You only declare a variable once, from then on just use "FANSTATE = FANTIMED", not "char FANSTATE = FANTIMED".

1 Like

Ahhhh! woops

And yet david_2018

const char  FANHUM    = '0';
const char  FANTIMED  = '1';
const char  FANONMAX  = '2';
const char  FANOFF    = '3';

// Temperature & humidity MQTT topics
const char *  MQTT_PUB_TEMP       = "esp/dht/b/temp"; //publish
const char *  MQTT_PUB_HUM        = "esp/dht/b/humid"; //publish
// Fan control topics
const char * MQTT_PUB_FAN_STATE   = "esp/dht/b/fanstate"; //publish
const char * MQTT_PUB_LIGHT_STATE ="esp/dht/b/lightstate"; //subscribe

char FANSTATE = FANHUM;
FANSTATE = FANTIMED;

errors with:
error: 'FANSTATE' does not name a type 30 | FANSTATE = FANTIMED; | ^~~~~~~~

That is an assignment outside of a function. Is that allowed?

Seemingly not. I wasn't aware. I've removed that test and it now compiles and I can publish to MQTT_SUB_LIGHT_STATE and the ESP8266 now receives the message on that topic and I can print and otherwise use the topic and the payload message. Thanks all!

I'll try and post the completed code, when I've finished adding the state control features

Having overcome the first issue, I've bumped into a related one.
As before I declare four state constants:

const char  FANHUM    = '0';
const char  FANTIMED  = '1';
const char  FANONMAX  = '2';
const char  FANOFF    = '3';

I also subscribe to a message whose payload I successfully extract in my callback function

void mqttCallback(char *topic, byte *payload, unsigned int length) {
  Serial.print ("Message arrived on Topic: ");
  Serial.println(topic);

  char message[5]={0x00}; //initialise blank (0x00) message as a char array of four characters with one extra for the compiler to append a terminating null char

  for(int i=0;i<length;i++){ // I added the moustaches. Fairly sure they were excluded in error
    message[i]=(char)payload[i]; //loop over the payload array and load each character into the message array
    //Serial.println(message[i]);
  }

  message[length]=0x00; //reset the message length or set the content of the message array to null??
  //Serial.println(message);

  String str_msg = String(message); //cast the message as a string  

  //Serial.println(str_msg);
// //NodeRed telling ESP8266 what the fanState should be - to set the LEDs and set the fanState variable to match
  if(topic == MQTT_SUB_LIGHT_STATE){
    if(strcmp(message,FANHUM)){ //set green LED on
      Serial.print(message);
      
    }
    else if(str_msg == FANTIMED){ //set green LED to flash on/off every 2 secs until done
      Serial.print(message);
      
    }
    else if(str_msg == FANONMAX){ //set green LED to flash on/off three times then stay off for ten secs and repeat until done
      Serial.print(message);

    }
    else if(str_msg == FANOFF){ //set red LED to flash on for 1 sec every 10 sec
      Serial.print(message);
      
    }
  }
}

But now the compiler reports errors converting char (ie str_msg) to const char * (eg FANTIMED) for each of the IF statements.

Now I'm confused because I removed the * from the consts at the top and I'd have thought comparing a char with a const char would be trivial.

Your message exists in message[]. I presume you're only expecting a single character at a time?

Why don't you just use (for example)...
if (message[0] == FANTIMED) { ...

There's no benefit in converting it to a String object (str_msg).

BTW... to tag someone into your post use an @ before their user name (example @nohspamjose) ... if not, they don't get notified when you reply.