Joining char to char to char

I've searched around and found in the examples from the Arduino that they sometimes add 2 strings together with the + symbol. I'm working with a char[] (char array?) from some of the example code of the MKR GSM1400. I've simplified what I'm trying to do to the very basics. I'm trying to break apart the URL that I send through to the MKR GSM 1400 so that I don't have to send the API keys for thingspeak, which I'm trying to connect to, in the Code, I can break them out and declare them in the secrets.h file.

So this entry would be in my arduino_secrets.h file:

#define secretwriteapikey "SOMEREDACTEDKEY"

While the rest of my code would look nice and clean and allow me to break the "field1writepath" char array into a couple of chars, or stings, whatever they are.

const char writeapikey[] = secretwriteapikey;
char field1writepath[] = "/update?api_key=",writeapikey,"&field1=1";

void setup() {
// put your setup code here, to run once:

}

void loop() {
// put your main code here, to run repeatedly:

Serial.println(field1writepath);

// do nothing forevermore:
for (;:wink:
;
}

If you try an compile that it will error as the comma is not a valid way to join two chars apparently. So how can I make up a char[] with multiple parts?

char[] = "part 1 " "part 2 " "part 3"

which should print out like "part 1 part 2 part 3" ???

Cheers Happy New Year

You can use strcat() or strncat():
http://www.cplusplus.com/reference/cstring/strcat/
http://www.cplusplus.com/reference/cstring/strncat/
Just be sure to size the buffer appropriately to hold the strings and don't forget space for the terminator.

Thanks Guys,

That makes sense and will test in a few minutes, but I think strcat will be the ticket for what I want to do. Also found this old post which verifies the same method:

http://forum.arduino.cc/index.php?topic=45499.0

Thanks All.

Got this going today, finally :slight_smile: just needed some time to look at it properly. Should be able to use this method now to break up the URL's I'm trying to send through to the MKR GSM 1400 and get it talking to Thingspeak a bit more nicely than just hard coding the URL's.

This should let me index through the fields in thingspeak etc.

Cheers for the assistance:

#include "arduino_secrets.h" 
// Please enter your sensitive data in the Secret tab or arduino_secrets.h

char writeapikey[] = SECRET_API_WRITE_KEY;
char url[200]; 

void setup() {
  // put your setup code here, to run once:
  
  char* part1 = "/update?api_key=";
  char* part2 = writeapikey;
  char* part3 = "&field1=1";
  
  strcpy(url, part1);
  strcpy(url + strlen(part1), part2);
  strcpy(url + strlen(part1), part3);

}

void loop() {
  // put your main code here, to run repeatedly:

  Serial.println(url);

  // do nothing forevermore:
  for (;;)
    ;
}
strcpy(url + strlen(part1), part2);
strcpy(url + strlen(part1), part3);

take a look at strcat()

Thanks for that, that will save some declaring of the variables, I can just write them in direct to the strcat command:

re-writte that code to now include both methods, with a preference now touse the strcat command.

#include "arduino_secrets.h" 
// Please enter your sensitive data in the Secret tab or arduino_secrets.h

char writeapikey[] = SECRET_API_WRITE_KEY;
char url[200]; 
char str[200];
  
void setup() {
  // put your setup code here, to run once:

  
  
  char* part1 = "/update?api_key=";
  char* part2 = writeapikey;
  char* part3 = "&field1=1";

  //Build URL via strcpy
  strcpy(url, part1);
  strcpy(url + strlen(part1), part2);
  strcpy(url + strlen(part1), part3);

  //Build URL via strcpy and strcat, which saves declaring variables for the bulk of the url
  strcpy (str,"update?api_key=");
  strcat (str,writeapikey);
  strcat (str,"&field1=1");
}

void loop() {
  // put your main code here, to run repeatedly:

  Serial.println(url);
  Serial.println(str);

  // do nothing forevermore:
  for (;;)
    ;
}

So I am now trying to move the building of the URL into a function and am having some trouble with getting it to compile. The code is the same basic layout as the example I was working on above, but now I am trying to pass 2 variables into the "writeThingspeak" function.

This will allow me to change the field number I'm writing to and the result that's being written easily. The full sketch as it stands currently is below:

/*
  Web client

 This sketch connects to the Thingspeal website using SSL through a MKR GSM 1400 board. Specifically,
 this example downloads performs a write and read operation to the thingspeak channel specified in the
 arduino_secrets.h file. 
 This sketch prints output to the Serial monitor.

 Circuit:
 * MKR GSM 1400 board
 * Antenna
 * SIM card with a data plan

 created 05 Feb 2018
 by SMGS
*/

// libraries
#include <MKRGSM.h>
#include <stdio.h>
#include <string.h>
#include "arduino_secrets.h" 
// Please enter your sensitive data in the Secret tab or arduino_secrets.h
// PIN Number
const char PINNUMBER[]     = SECRET_PINNUMBER;
// APN data
const char GPRS_APN[]      = SECRET_GPRS_APN;
const char GPRS_LOGIN[]    = SECRET_GPRS_LOGIN;
const char GPRS_PASSWORD[] = SECRET_GPRS_PASSWORD;

// Thingspeak Secret Settings
char writeapikey[]      = secretwriteapikey;
char readapikey[]       = secretreadapikey;
char channelid[]        = secretchannelid;

// initialize the library instance
GSMSSLClient client;
GPRS gprs;
GSM gsmAccess;
GSMLocation location;

// Domain name and port that we will connect too (for example: api.thingspeak.com)
char server[] = "api.thingspeak.com";
int port = 443; // port 443 is the default for HTTPS
// Remainder of the URL is crafted together in the writeThingspeak() or readThingspeak() functions which take
// some arguments such as field and result, the crafted URL is returned from the function for later use.
char URL[200];
  
void setup() {

  // initialize serial communications and wait for port to open:
  Serial.begin(9600);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  }

  Serial.println("Starting Arduino web client.");
  // connection state
  boolean connected = false;

  // After starting the modem with GSM.begin()
  // attach the shield to the GPRS network with the APN, login and password
  while (!connected) {
    if ((gsmAccess.begin(PINNUMBER) == GSM_READY) &&
        (gprs.attachGPRS(GPRS_APN, GPRS_LOGIN, GPRS_PASSWORD) == GPRS_READY)) {
      connected = true;
    } else {
      Serial.println("Not connected");
      delay(1000);
    }
  }
}

void loop() {
  char result = 200;
  char field = 1;

  Serial.println("Print the completed /crafted URL: ");
  Serial.println(writeThingspeak(field,result));
  // URL = writeThingspeak(field,result);
    
  Serial.println("connecting...");

  // if you get a connection, report back via serial:
  if (client.connect(server, port)) {
    Serial.println("Read connected");
    // Make a HTTP request:
    client.print("GET ");
    client.print(URL);
    client.println(" HTTP/1.1");
    client.print("Host: ");
    client.println(server);
    client.println("Connection: close");
    client.println();
  } else {
    // if you didn't get a connection to the server:
    Serial.println("connection failed");
  }

  delay(200);
  
  // if there are incoming bytes available
  // from the server, read them and print them:
  if (client.available()) {
    char c = client.read();
    Serial.print(c);
  }

    // do nothing forevermore:
    for (;;)
      ;

  //}
}

char writeThingspeak(char fieldNumber, char result) {

  // An Complete Example URL to Update Channel Field1 via Thingspeak
  // GET https://api.thingspeak.com/update?api_key=1234567890ABC&field1=0
  // Our URL is broken down below to give us the ability to update certain portions of the URL, such as the field number etc

  char writeURLField[200];
  char thingspeak_write_update[17] = "/update?api_key=";
  char thingspeak_write_field[8] = "&field";
  
  //Build the custom Write URL to send data to my Thingspeak Channel via strcpy and strcat
  strcpy (writeURLField,thingspeak_write_update);
  strcat (writeURLField,writeapikey);
  strcat (writeURLField,thingspeak_write_field);
  strcat (writeURLField,fieldNumber);
  strcat (writeURLField,"=");
  strcat (writeURLField,result);

  return writeURLField;

} //end of writeThingspeak

Where a couple of things have been declared within the "arduino_secrets.h" file as below:

#define SECRET_PINNUMBER     ""
#define SECRET_GPRS_APN      "internet" // replace your GPRS APN
#define SECRET_GPRS_LOGIN    ""    // replace with your GPRS login
#define SECRET_GPRS_PASSWORD "" // replace with your GPRS password

// Thingspeak Settings
#define secretwriteapikey  "1234567890000002"
#define secretreadapikey  "1234567890000001"
#define secretchannelid   "123456"

This is probably the wrong way to do it, I say that as it gives me a few errors and won't compile. I suspect my issue has something to do with the fact that I'm using character arrays?

Compiler Issues:

Arduino: 1.8.5 (Windows 10), Board: "Arduino MKR GSM 1400"

20180202-5.ino: In function 'char writeThingspeak(char, char)':

20180202-5:130: error: invalid conversion from 'char' to 'const char*' [-fpermissive]

strcat (writeURLField,fieldNumber);

^

In file included from c:\appdata\local\arduino15\packages\arduino\tools\arm-none-eabi-gcc\4.8.3-2014q1\arm-none-eabi\include\stdlib.h:11:0,

from C:\AppData\Local\Arduino15\packages\arduino\hardware\samd\1.6.17\cores\arduino/Arduino.h:25,

from sketch\GsmSSLWebClient-20180202-5.ino.cpp:1:

c:\appdata\local\arduino15\packages\arduino\tools\arm-none-eabi-gcc\4.8.3-2014q1\arm-none-eabi\include\string.h:26:8: error: initializing argument 2 of 'char* strcat(char*, const char*)' [-fpermissive]

char *_EXFUN(strcat,(char *__restrict, const char *__restrict));

^

20180202-5:132: error: invalid conversion from 'char' to 'const char*' [-fpermissive]

strcat (writeURLField,result);

^

In file included from c:\appdata\local\arduino15\packages\arduino\tools\arm-none-eabi-gcc\4.8.3-2014q1\arm-none-eabi\include\stdlib.h:11:0,

from C:\AppData\Local\Arduino15\packages\arduino\hardware\samd\1.6.17\cores\arduino/Arduino.h:25,

from sketch\20180202-5.ino.cpp:1:

c:\appdata\local\arduino15\packages\arduino\tools\arm-none-eabi-gcc\4.8.3-2014q1\arm-none-eabi\include\string.h:26:8: error: initializing argument 2 of 'char* strcat(char*, const char*)' [-fpermissive]

char *_EXFUN(strcat,(char *__restrict, const char *__restrict));

^

20180202-5:134: error: invalid conversion from 'char*' to 'char' [-fpermissive]

return writeURLField;

^

exit status 1
invalid conversion from 'char' to 'const char*' [-fpermissive]

@Delta_G
That is a good explanation. Thanks.

Delta_G:

char writeThingspeak(char fieldNumber, char result)

So you're passing in the 1 and the 200 as actual numbers. But the code you're passing them to is expecting char strings. So the 1 needs to be an array of 2 characters with the first being a 49 (ascii code for 1) and the second being 0 (the null terminator). For 200 you'd need an array of 4 characters, a '2' (aka 50) followed by two '0's (aka 48) and then a 0.

You can use itoa to convert a number into its ascii representation and then pass that to your strcat functions.

So basically it is something to do with the way the variables

char result = "200";
char field = "1";

  Serial.println(writeThingspeak(field,result));
  // URL = writeThingspeak(field,result);

It's an conversion happening in the process of declaring the variable type as a char and sending it into the function?

char writeThingspeak(char fieldNumber, char result)

So could I just re-write my function differently to allow me to pass a char instead of a char-string?

I'm missing why I need to convert my existing char value into ASCII code?

Thanks for the assistance here, I guess I'm still struggling to understand a bit, as to why the function I made is expecting an char string (ASCII) formatted text and the rest of the code works well without the need to convert the text into ASCII?

i.e. I store the domain name and the URL in a char arrays and pass those to a library function without converting it to ASCII.

I understand that a web URL would generally be done in ASCII, but for my function I just need to pass it some values to concatenate together. Is it strcpy or strcat that expect the characters to be in ASCII format?