0

A newbie in Arduino- and I'm trying to concatenate string and chars ( well in python it is quite different ).

I'm trying to post a MQTT message- constructed following format to the client.publish(outTopic, "["+outTopic+"]"+ msg)

while outTopic is a char* variable, and msg is char- but I get an error for such concatenation.

please your help

#include <ESP8266WiFi.h>
#include <PubSubClient.h>
// GPIOs on SONOFF board
int LED_SONOFF = 13;
int REL_SONOFF = 12;
int PIN_SW = 14;
const char* ssid = "HomeNetwork_2.4G";
const char* password = "pswd";
const char* mqtt_server = "192.168.2.113";
WiFiClient espClient;
PubSubClient client(espClient);
char msg[50];
const char* outTopic = "HomePi/Dvir/Messages";
const char* inTopic = "HomePi/Dvir/Windows/SONOFF";
const char* inTopic2 = "HomePi/Dvir/Windows/All";
const char* clientID = "Sonoff#1";
String m1, m2;
void start_wifi() {
 WiFi.mode(WIFI_STA);
 WiFi.begin(ssid, password);
 while (WiFi.status() != WL_CONNECTED) {
 delay(500);
 Serial.print(".");
 }
 Serial.println("");
 Serial.println("WiFi connected"); 
 Serial.print("IP address: ");
 Serial.println(WiFi.localIP()); 
}
void setup() {
 start_wifi(); // start wifi service
 Serial.begin(115200); // start serial service
 delay(10);
 // define sonoff gpios
 pinMode(LED_SONOFF, OUTPUT);
 pinMode(REL_SONOFF, OUTPUT);
 pinMode(PIN_SW, INPUT_PULLUP); // GPIO14 has a pullup resistor
 digitalWrite(LED_SONOFF,HIGH); // LED high is OFF
 digitalWrite(REL_SONOFF,LOW); 
 // start mqtt
 client.setServer(mqtt_server, 1883);
 client.setCallback(callback); 
}
void switch_on() {
 digitalWrite(REL_SONOFF,HIGH);
 digitalWrite(LED_SONOFF, LOW); // LED ON
 pub_mqtt("Switch ON");
}
void switch_off() {
 digitalWrite(REL_SONOFF,LOW);
 digitalWrite(LED_SONOFF, HIGH); // LED OFF
 pub_mqtt("Switch OFF");
}
void callback(char* topic, byte* payload, unsigned int length) {
 Serial.print("Message arrived [");
 Serial.print(topic);
 Serial.print("] ");
 for (int i = 0; i < length; i++) {
 Serial.print((char)payload[i]);
 }
 Serial.println();
 if ((char)payload[0] == '1') {
 switch_on(); 
 } 
 if ((char)payload[0] == '0') {
 switch_off();
 Serial.print("payload: ");
 Serial.println(payload[0]);
 }
}
void reconnect() {
 while (!client.connected()) {
 Serial.print("Attempting MQTT connection...");
 if (client.connect("ESP8266Client")) {
 Serial.println("connected");
 client.publish(outTopic, "Connected");
 client.subscribe(inTopic);
 m1="Subscribed to: "+inTopic;
 client.publish(outTopic, m1);
 if (inTopic2 !=""){
 client.subscribe(inTopic2);
 m2="Subscribed to: ";//+ String(inTopic2);
 client.publish(outTopic, m2);
 }
 } else {
 Serial.print("failed, rc=");
 Serial.print(client.state());
 Serial.println(" try again in 5 seconds");
 delay(5000);
 }
 }
}
void pub_mqtt(char* msg) {
 client.publish(outTopic, msg);
}
void loop() {
 if (!client.connected()) {
 reconnect();
 }
 client.loop();
 if (digitalRead(PIN_SW)==1) {
 if (digitalRead(REL_SONOFF)!=LOW) {
 switch_off();
 }
 }
 else if (digitalRead(PIN_SW)==0) {
 if (digitalRead(REL_SONOFF)!=HIGH){
 switch_on();
 }
 }
 delay(100);
}
VE7JRO
2,51519 gold badges27 silver badges29 bronze badges
asked Aug 11, 2018 at 14:18
1
  • Likely it would be best if you created a new string in which you place what you want to pass to the called method. Guessing, you have asked if the C/C++ compiler could implicitly do this by asking it to arrange for pulling out bits of the string from flash memory (the const outTopic and the "[" characters you added in the line of code) with bits from RAM (the string msg). Commented Aug 11, 2018 at 14:37

1 Answer 1

2

You can't simply concatenate C strings like that. Instead you have to build them up into a new string. For formatting like that the simplest way is with sprintf:

char outMessage[strlen(outTopic) + strlen(msg) + 3]; // Room for topic, message, [ and ] and terminating 0円
sprintf(outMessage, "[%s]%s", outTopic, msg);
client.publish(outTopic, outMessage);

Another method is with strcpy and strcat:

char outMessage[strlen(outTopic) + strlen(msg) + 3]; // Room for topic, message, [ and ] and terminating 0円
strcpy(outMessage, "[");
strcat(outMessage, outTopic);
strcat(outMessage, "]");
strcat(outMessage, msg);
client.publish(outTopic, outMessage);

You have to ensure that your "holding" string outMessage is big enough to hold everything you want to send, plus a terminating NULL character, otherwise your program will crash.

Another way of creating the "holding" variable is with alloca(). That allocates bytes on the stack for a variable - just like malloc() does on the heap, but doesn't require free()ing because it's on the stack and is reclaimed when the function exits:

char *outMessage = (char *)alloca(strlen(outTopic) + strlen(msg) + 3);
answered Aug 11, 2018 at 14:33
8
  • thank you- i fund first method more short and sensable. does it matter that outTopic is char* ? Commented Aug 11, 2018 at 16:26
  • %s connects to a char * data type. Commented Aug 11, 2018 at 16:26
  • I was referring to char outMessage[strlen(outTopic) + strlen(msg) + 3]; Commented Aug 11, 2018 at 16:29
  • char *foo and char foo[x] are essentially the same. The second is a char * with memory allocation added in. Commented Aug 11, 2018 at 16:30
  • @Mejnko - can you please explain why +3 is needed, since for purpose of string concatenation, it is not needed - does it relevent for sending ? Commented Aug 12, 2018 at 19:08

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.