sending variables to a function

Really sorry,

following advice on this forum I am trying to be more mindful of my use of variable types.

I am trying to send two char variables to a function, this is receiving an MQTT topic and payload:

void callback(char* topic, char* payload, unsigned int length) {
  payload[length] = '\0';
  Serial.print(topic);
  Serial.print(" - ");
  Serial.println(payload);
  actions(topic, payload);
}

in the actions function I was going to use switch...case as I understand that these work with chars, but somewhere, some how the topic an payload in the function are not readable:

void actions(char topic, char payload) {
  Serial.print(topic);
  switch (topic) {
    case 'alarm/info':
      message(payload);
      break;
    case 'alarm/sound':
      soundalarm();
      break;
    case 'alarm/buzzer':
      soundalarm();
      break;      
    default:
      // if nothing else matches, do the default
      // default is optional
      break;
  }
}

this gives:

20:03:58.099 -> alarm/buzzer - on -// topic fine in first function
20:03:58.099 -> ⸮ //topic not fine in second function
20:03:58.655 -> alarm/buzzer - off
20:03:58.655 -> ⸮

in the serial monitor

I know this will be something silly, but I cannot find it

case 'alarm/info'single quote, single character. (Generally)

ah ok.

If I use double quotes

  switch (topic) {
    case "alarm/info":
      message(payload);
      break;

I get:

i_action_from_mqqt:4:10: error: conversion from pointer type 'const char (*)[11]' to arithmetic type 'int' in a constant-expression

case "alarm/info":

A case must be an integer type.
So it can't be a String or a string.

is char a single character then, I thought it was an array of characters?

A char is a single character.

ok, now I am totally confused:

void callback(char* topic, char* payload, unsigned int length) {
payload[length] = '\0';
Serial.print(topic);
Serial.print(" - ");
Serial.println(payload);
actions(topic, payload);
}

gives: "alarm/buzzer - on" which is more than one character.

so it displays the char variable fine.

it is only when it goes to the actions function that it cannot be read/

char* is a char pointer.
It points to a char, that may be followed by another char, and another...and then a zero.

Aka a C string.

Thank you, I think I get it, so would I be better converting the char* topic to a string?

In your callback() function, topic and payload are character pointers, but your action() function is expecting characters, not character pointers (turn up the compiler warnings and you will see it complain about invalid conversion from char * to char).

The switch statement will work with single characters, but not with strings (null-terminated character arrays). With what you are doing, strcmp and if statements would be easy to use, assuming that topic points to a null-terminated character array.

void actions(char * topic, char * payload) {
  Serial.print(topic);
  if (strcmp(topic, "alarm/info") == 0) {
    message(payload);
  } else if (strcmp(topic, "alarm/sound") == 0) {
    soundalarm();
  } else if (strcmp(topic, "alarm/buzzer") == 0) {
    soundalarm();
  }
}

That's perfect.

Thank you both for your help.

sorry, not sure if this is linked. as soon as I uncomment out the contents of the function, then it starts a boot loop:

void actions(char * topic, char * payload) {
  Serial.println(topic);
  if (strcmp(topic, "alarm/info") == 0) {
    message(payload);
  } else if (strcmp(topic, "alarm/sound") == 0) {
    soundalarm(payload); 
  } else if (strcmp(topic, "alarm/buzzer") == 0) {
    soundbuzzer(payload);
  }
}


void soundalarm(char * payload) {
//  if (strcmp(payload,"on") ==0)
//  {
//    Serial.println("whoo whooo");
//    digitalWrite(strobe, HIGH);
//    digitalWrite(siren, HIGH);
//  }
//  else
//  {
//
//    Serial.println("quiet");
//    digitalWrite(strobe, LOW);
//    digitalWrite(siren, LOW);
//  }
}

void soundbuzzer(char * payload) {
//  Serial.println(payload);
//    if (strcmp(payload,"on") ==0)
//  {
//    Serial.println("buzz");
//    digitalWrite(buzzer, HIGH);
//  }
//  else
//  {
//    Serial.println("shhhhh");
//    digitalWrite(buzzer, LOW);
//  }
}

09:53:34.490 → Attempting to connect to WPA SSID: xxxxxxx
09:53:34.525 → 1564998817
09:53:34.525 → 1564998817
09:53:49.588 → You’re connected to the networkAttempting to connect to WPA SSID: xxxxxx
09:53:53.190 → 1564998835
09:53:53.190 → 1564998835

I have attached the whole code, sorry it is split into tabs

a_variables.ino (1.02 KB)

sketch_apr03a.ino (2 Bytes)

b_presetup.ino (3.18 KB)

c_setup.ino (6.83 KB)

d_main_loop.ino (5.76 KB)

e_access_conrtol.ino (11.3 KB)

f_comm_setup.ino (2.33 KB)

g_lcd.ino (2.55 KB)

h_keypad.ino (429 Bytes)

i_action_from_mqqt.ino (904 Bytes)

You should get into the habit of enclosing all your literal string in the F macro.

Like this: F("abcdefghij")

It re-locates these string to flash memory where your code resides and that you have a great deal more of available, and hence saves a lot of space in SRAM for other variables.

If you don't, and your sketch uses a lot of literal strings then you will quickly run out of memory.

Arduino provides a version of all the string function that can handle literal strings stored in flash memory.

They are simply the regular c string functions with '_P' appended to the end. Like so:

``void actions(char * topic, char * payload) {
Serial.print(topic);
if (strcmp_P(topic, F("alarm/info")) == 0) {
message(payload);
} else if (strcmp_P(topic, F("alarm/sound")) == 0) {
soundalarm();
} else if (strcmp_P(topic, F("alarm/buzzer")) == 0) {
soundalarm();
}
}

thank you, will do.

Will that fix the loop too?

edit, no that will not compile:
Arduino: 1.8.9 (Windows 10), Board: "Arduino/Genuino Mega or Mega 2560, ATmega2560 (Mega 2560)"

\Arduino\AccessControlv_functions\i_action_from_mqqt.ino: In function 'void actions(char*, char*)':

i_action_from_mqqt:3:38: error: cannot convert 'const __FlashStringHelper*' to 'const char*' for argument '2' to 'int strcmp_P(const char*, const char*)'

if (strcmp_P(topic, F("alarm/info")) == 0) {

^

i_action_from_mqqt:5:46: error: cannot convert 'const __FlashStringHelper*' to 'const char*' for argument '2' to 'int strcmp_P(const char*, const char*)'

} else if (strcmp_P(topic, F("alarm/sound")) == 0) {

^

i_action_from_mqqt:7:47: error: cannot convert 'const __FlashStringHelper*' to 'const char*' for argument '2' to 'int strcmp_P(const char*, const char*)'

} else if (strcmp_P(topic, F("alarm/buzzer")) == 0)) {

^

i_action_from_mqqt:7:54: error: expected primary-expression before ')' token

} else if (strcmp_P(topic, F("alarm/buzzer")) == 0)) {

^

exit status 1
cannot convert 'const __FlashStringHelper*' to 'const char*' for argument '2' to 'int strcmp_P(const char*, const char*)'

^

exit status 1
cannot convert 'const __FlashStringHelper*' to 'const char*' for argument '2' to 'int strcmp_P(const char*, const char*)'

strcmp_P doesn't use the F() function, it uses PSTR()

void actions(char * topic, char * payload) {
  Serial.print(topic);
  if (strcmp_P(topic, PSTR("alarm/info")) == 0) {
    message(payload);
  } else if (strcmp_P(topic, PSTR("alarm/sound")) == 0) {
    soundalarm();
  } else if (strcmp_P(topic, PSTR("alarm/buzzer")) == 0) {
    soundalarm();
  }
}

I appreciate the comments, I really do, but they have not fixed the issue of the loop when the functions are uncommented