Multiple variable in string

Hello

a few weeks ago i recived my first arduino EtherTen.
this is a arduino uno with Ethernet.

I want to make a weather station.

What i did:

  1. Add all components to the arduino
  2. Let the code write all variable to the serial console
  3. add networking
  4. let the arduino call a http string with static value

So far everything worked

when i want to combine some variable to a link the result is a blank line
what do i wrong?

the intresting part of the code

  String RFall = String(weather.total_rainfall(), DEC);
 HString = "/send?{%22action%22:%22control%22,%22code%22:{%22device%22:%22RainMesurement%22,%22values%22:{%22label%22:%22" + RFall + "%22,%22color%22:%22black%22}}}";
      Serial.println(HString); 
      Pilight(HString);

the full part of the code

/*
VLD Weather station
25-04-2015

 */
const int Ver = 5;


#include <TimerOne.h>
#include <Weather.h>
#include <SPI.h>
#include <Ethernet.h>
#include <OneWire.h>

// pin assignment
const int RainPin = 6;       // pin for raindrop sensor
const int TempPin = 5;       // pin for onewire devices
const int ledPin =  13;      // Pin for onboard LED
/*weather libarie has fixed pins
RainGauge 2
Anemometer 3
WindVane A3
*/

byte myserver[] = { 172, 16, 20, 134 }; // Pilight server

//default variable
int RainState = 0;        // the state of the raindrop sensor
int PRainState = 0;        // see if ther is anything changed
#define SERIAL_BAUDRATE 9600

byte mac[] = {
  0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED
};  // IF no onewire device is found use this mac
EthernetClient client;
OneWire ds(TempPin); // Set up DS18B20 sensor
  String HString;
void setup() {
    Serial.begin(SERIAL_BAUDRATE); 
    Serial.print("Weatherstation V"); 
    Serial.print(Ver);
    Serial.println(); 

    pinMode(RainPin, INPUT);   
    byte i;
    byte dsAddress[8];
    weather.initialize();
    
    delay( 500 ); // Give the Ethernet chipset time to fully initialise

    ds.reset_search();  // Start the search with the first device    
   if ( !ds.search(dsAddress) )
  {
    Serial.println( "none found. Using default MAC address." );
  } else {
    // Offset array to skip DS18B20 family code, and skip mac[0]
    mac[1] = dsAddress[3];
    mac[2] = dsAddress[4];
    mac[3] = dsAddress[5];
    mac[4] = dsAddress[6];
    mac[5] = dsAddress[7];
  }

  Ethernet.begin( mac );
  Serial.print( "My IP address: " );
  Serial.println( Ethernet.localIP() );

}


void loop() {
   //Raindrop sensor
  RainState = digitalRead(RainPin);      // read the state of the Raindropsensor value:
  // check if the Sensor is wet. if it is, the RainState is HIGH:
  if (RainState == LOW) {     
 if (PRainState == 0) {          // and it was not raining
HString = "/send?{%22action%22:%22control%22,%22code%22:{%22device%22:%22Rain%22,%22state%22:%22on%22}}";
      Pilight(HString); // call pilight function to inform the pilight server about the rain   
 PRainState=1;
 }
  } 
  
  
  else {
   if (PRainState == 1) {
    // turn LED off:
HString = "/send?{%22action%22:%22control%22,%22code%22:{%22device%22:%22Rain%22,%22state%22:%22off%22}}";
      Pilight(HString); // call sendRainOn function below when it rains   
 PRainState=0;
 }
  }
      Serial.println("regenval"); 
  String RFall = String(weather.total_rainfall(), DEC);
  if (PRainState == 0) { 
 HString = "/send?{%22action%22:%22control%22,%22code%22:{%22device%22:%22RainMesurement%22,%22values%22:{%22label%22:%22" + RFall + "%22,%22color%22:%22black%22}}}";
      Serial.println(HString); 
      Pilight(HString); 
} else {
HString = "/send?{%22action%22:%22control%22,%22code%22:{%22device%22:%22RainMesurement%22,%22values%22:{%22label%22:%22" + RFall + "%22,%22color%22:%22red%22}}}";
        Pilight(HString); 
}

  String WName = String(weather.wind_direction_name());
 HString = "/send?{%22action%22:%22control%22,%22code%22:{%22device%22:%22WindDirection%22,%22values%22:{%22label%22:%22" + WName + "%22,%22color%22:%22black%22}}}";
      Pilight(HString);  
 
 

      
  String WSpeed = String(weather.wind_speed ,DEC);      
if (weather.wind_speed < 24)  {
HString = "/send?{%22action%22:%22control%22,%22code%22:{%22device%22:%22WindSpeed%22,%22values%22:{%22label%22:%22" + WSpeed + "%22,%22color%22:%22black%22}}}";
      Pilight(HString); 
} else {
  HString = "/send?{%22action%22:%22control%22,%22code%22:{%22device%22:%22WindSpeed%22,%22values%22:{%22label%22:%22" + WSpeed + "%22,%22color%22:%22black%22}}}";
      Pilight(HString); 
}
  
  
    // information from the weatherstation
    Serial.print("Windrichting:  ");  
    Serial.print(weather.wind_direction_name());
    Serial.print(" ( ");
    Serial.print(weather.wind_direction_degs());
    Serial.print(" )");
    Serial.println();
    Serial.print("Windkracht:    ");  
    Serial.print(weather.wind_speed);
    Serial.print(" KM/H");
    Serial.println();
    Serial.print("Regenval:    ");  
    Serial.print(weather.total_rainfall());
    Serial.print(" mm");
    Serial.println();
    Serial.print("Regen:    ");  
    Serial.print(PRainState);
    Serial.println();
    
 
    
//temperature

 byte i;
  byte present = 0;
  byte type_s;
  byte data[12];
  byte addr[8];
  float celsius;
  
  if ( !ds.search(addr)) {
    ds.reset_search();
    delay(250);
    return;
  }
  


  if (OneWire::crc8(addr, 7) != addr[7]) {
      Serial.println("CRC is not valid!");
      return;
  }

 
  // the first ROM byte indicates which chip
  switch (addr[0]) {
    case 0x10:
      type_s = 1;
      break;
    case 0x28:
      type_s = 0;
      break;
    case 0x22:
      type_s = 0;
      break;
    default:
      Serial.println("Device is not a DS18x20 family device.");
      return;
  } 

  ds.reset();
  ds.select(addr);
  ds.write(0x44, 1);        // start conversion, with parasite power on at the end
  
  delay(1000);     // maybe 750ms is enough, maybe not
  // we might do a ds.depower() here, but the reset will take care of it.
  
  present = ds.reset();
  ds.select(addr);    
  ds.write(0xBE);         // Read Scratchpad


  for ( i = 0; i < 9; i++) {           // we need 9 bytes
    data[i] = ds.read();

  }
  


  // Convert the data to actual temperature
  // because the result is a 16 bit signed integer, it should
  // be stored to an "int16_t" type, which is always 16 bits
  // even when compiled on a 32 bit processor.
  int16_t raw = (data[1] << 8) | data[0];
  if (type_s) {
    raw = raw << 3; // 9 bit resolution default
    if (data[7] == 0x10) {
      // "count remain" gives full 12 bit resolution
      raw = (raw & 0xFFF0) + 12 - data[6];
    }
  } else {
    byte cfg = (data[4] & 0x60);
    // at lower res, the low bits are undefined, so let's zero them
    if (cfg == 0x00) raw = raw & ~7;  // 9 bit resolution, 93.75 ms
    else if (cfg == 0x20) raw = raw & ~3; // 10 bit res, 187.5 ms
    else if (cfg == 0x40) raw = raw & ~1; // 11 bit res, 375 ms
    //// default is 12 bit resolution, 750 ms conversion time
  }
  celsius = (float)raw / 16.0;
     

Serial.println("");
String Adr = String(addr[7], HEX);



      
  Serial.print("Temp" + Adr + " = " + celsius);
  Serial.print((char)176);
  Serial.println("C");
    

HString = "/send?{%22action%22:%22control%22,%22code%22:{%22device%22:%22Temp" + Adr + "%22,%22values%22:{%22temperature%22:" + Adr + ",%22color%22:%22black%22}}}";
      Pilight(HString);  



    
    delay(5000);
}


void Pilight(String HString) //client function to send data to pilight
{
  if (client.connect(myserver, 5001)) {  //starts client connection, checks for connection


  
    client.print("GET ");
    client.print(HString);
    client.print(" HTTP/1.0"); 
    client.println(); //end of get request
  } 
  else {
    Serial.println("connection failed"); //error message if no client connect
    Serial.println();
  }

  while(client.connected() && !client.available()) delay(1); //waits for data
  while (client.connected() || client.available()) { //connected or data available
    char c = client.read(); //gets byte from ethernet buffer
    Serial.print(c); //prints byte to serial monitor 
  }
 Serial.println();

  client.stop(); //stop client
} :stuck_out_tongue:

Can't do this

HString = "/send?{%22action%22:%22control%22,%22code%22:{%22device%22:%22RainMesurement%22,%22values%22:{%22label%22:%22" + RFall + "%22,%22color%22:%22black%22}}}";

action, control, device, etc... is now a string not a variable.

try using sprintf

char HString [150];
sprintf(HString,"/send?{\"%s\"%s}", action, control);

http://www.cplusplus.com/reference/cstdio/sprintf/

String RFall = String(weather.total_rainfall(), DEC);

What do you see if you print RFall after this ? Is it what you expect ?

or you can do this too since it's a String

HString = "/send?{%22" + action + "%22:%22" + control + "%22,%22" + code + "%22: .......

Hey

Thanks for the answer

the only variable in this string is RFall the rest is static text

should it be something like ...

sprintf(HString,"/send?{%22action%22:%22control%22,%22code%22:{%22device%22:%22RainMesurement%22,%22values%22:{%22label%22:%22"%s"%22,%22color%22:%22black%22}}}", RFall);

can i also put a format in it so i can remove this conversion?

String RFall = String(weather.total_rainfall(), DEC);

Many thanks for your support

@UKHeliBob

Apart from the number of digits: yes this is exactly what i need i added the part bellow to fix the number of digits

  RFall.remove(4);

@mistergreen I think that is exactly what i did Action and Control are no variable (at least for the arduino part of my project) there is in this string only 1 variable called RFall (total mm of Rain Fall)

When i use

sprintf(HString,"/send?{%22action%22:%22control%22,%22code%22:{%22device%22:%22RainMesurement%22,%22values%22:{%22label%22:%22%s%22,%22color%22:%22black%22}}}", RFall);

i got

weather6.ino:98:186: error: cannot convert 'String' to 'char*' for argument '1' to 'int sprintf(char*, const char*, ...)'

When i use...I get...

What did you expect, and why did you expect that? The % character introduces a format specifier. 22 is not a format specifier. Each format specifier needs to have a variable, of the correct type, based on the format specifier, associated with it.

And, I'm quite certain that is NOT what you got.

hey

i am sorry i made a copy paste error.
it is corrected now

and also sorry for my english it is not my native language.

i need something like

{"action":"control","code":{........

since it is a http string i replaced the quotes with %22
So i first convert the original variable to a string with

  String RFall = String(weather.total_rainfall(), DEC);

then i combined the 3 (text + variable + text) strings to one new string
ref: http://www.arduino.cc/en/Tutorial/StringAdditionOperator

"....{%22label%22:%22" + RFall + "%22,%22color%22:%22black%22}...."

the result was a empty string

After mistergreen’s post i tried the code bellow

sprintf(HString,"/send?{%22action%22:%22control%22,%22code%22:{%22device%22:%22RainMesurement%22,%22values%22:{%22label%22:%22%s%22,%22color%22:%22black%22}}}", RFall);

lets say the variable RFall has a value of 1.23 i expected

/send?{%22action%22:%22control%22,%22code%22:{%22device%22:%22RainMesurement%22,%22values%22:{%22label%22:%221.23%22,%22color%22:%22black%22}}}

however this will never work since it use the % for the variable

when i use (no variable in the string here)

String HString = "/send?{%22action%22:%22control%22,%22code%22:{%22device%22:%22Rain%22,%22state%22:%22on%22}}";
      Pilight(HString); // call pilight function to inform the pilight server about the rain

then it starts the client part of the code and the pilight server knows it is raining

void Pilight(String HString) //client function to send data to pilight
{
  if (client.connect(myserver, 5001)) {  //starts client connection, checks for connection
    client.print("GET ");
    client.print(HString);
    client.print(" HTTP/1.0"); 
    client.println(); //end of get request
  } 
  else {
    Serial.println("connection failed"); //error message if no client connect
  }

  while(client.connected() && !client.available()) delay(1); //waits for data
  while (client.connected() || client.available()) { //connected or data available
    char c = client.read(); //gets byte from ethernet buffer
    Serial.print(c); //prints byte to serial monitor 
  }
 Serial.println();

  client.stop(); //stop client
}
void Pilight(String HString) //client function to send data to pilight

should be:

void Pilight(char *HString) //client function to send data to pilight

Then, you can't use sprintf() write a String to a string. So, RFall should NOT be a String.

So i first convert the original variable to a string with

No, you don't. A string and a String are two completely different things. They are NOT interchangeable.

What type does weather.total_rainfall() return? There is no reason to wrap that in a String.

If it returns a float, then you need to use dtostrf() to convert it to a string, which you can then write into the string using sprintf() with the %s format specifier.

If it returns an int, use the %d format specifier.

Hey

thanks for the answer
when i use the code below there is a endless loop (back to the setup part)

      char *RFall;
    dtostrf(weather.total_rainfall(),4, 2, RFall);

i have removed all the other components from the loop part
i also removed (comment out) the HString lines to first test the conversion of the RFall variable

const int Ver = 7;


#include <TimerOne.h>
#include <Weather.h>
#include <SPI.h>
#include <Ethernet.h>
#include <OneWire.h>

// pin assignment
const int RainPin = 6;       // pin for raindrop sensor
const int TempPin = 5;       // pin for onewire devices
const int ledPin =  13;      // Pin for onboard LED
/*weather libarie has fixed pins
RainGauge 2
Anemometer 3
WindVane A3
*/

byte myserver[] = { 172, 16, 20, 134 }; // Pilight server

//default variable
int RainState = 0;        // the state of the raindrop sensor
int PRainState = 0;        // see if ther is anything changed
#define SERIAL_BAUDRATE 9600

byte mac[] = {
  0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED
};  // IF no onewire device is found use this mac
EthernetClient client;
OneWire ds(TempPin); // Set up DS18B20 sensor
char *HString;
void setup() {
    Serial.begin(SERIAL_BAUDRATE); 
    Serial.print("Fnetonline Weatherstation V"); 
    Serial.print(Ver);
    Serial.println(); 

    pinMode(RainPin, INPUT);   
    byte i;
    byte dsAddress[8];
    weather.initialize();
    
    delay( 500 ); // Give the Ethernet chipset time to fully initialise

    ds.reset_search();  // Start the search with the first device    
   if ( !ds.search(dsAddress) )
  {
    Serial.println( "none found. Using default MAC address." );
  } else {
    // Offset array to skip DS18B20 family code, and skip mac[0]
    mac[1] = dsAddress[3];
    mac[2] = dsAddress[4];
    mac[3] = dsAddress[5];
    mac[4] = dsAddress[6];
    mac[5] = dsAddress[7];
  }

  Ethernet.begin( mac );
  Serial.print( "My IP address: " );
  Serial.println( Ethernet.localIP() );

}

void loop() {

      Serial.println("regenval"); 
      char *RFall;
  dtostrf(weather.total_rainfall(),4, 2, RFall);  
        Serial.println(RFall);
  
  if (PRainState == 0) { 
///////////////////////////////////////////////////////////////////////////////////////// HString = "/send?{%22action%22:%22control%22,%22code%22:{%22device%22:%22RainMesurement%22,%22values%22:{%22label%22:%22" + RFall + "%22,%22color%22:%22black%22}}}";
      Serial.println(HString); 
      Pilight(HString); 
} else {
/////////////////////////////////////////////////////////////////////////////////////////HString = "/send?{%22action%22:%22control%22,%22code%22:{%22device%22:%22RainMesurement%22,%22values%22:{%22label%22:%22" + RFall + "%22,%22color%22:%22red%22}}}";
        Pilight(HString); 
              Serial.println(HString); 
}
    
    delay(5000);
}


void Pilight(char *HString) //client function to send data to pilight
{
  if (client.connect(myserver, 5001)) {  //starts client connection, checks for connection


  
    client.print("GET ");
    client.print(HString);
    client.print(" HTTP/1.0"); 
    client.println(); //end of get request
    Serial.println("connection finished"); //error message if no client connect
  } 
  else {
    Serial.println("connection failed"); //error message if no client connect
    Serial.println();
  }

  while(client.connected() && !client.available()) delay(1); //waits for data
  while (client.connected() || client.available()) { //connected or data available
    char c = client.read(); //gets byte from ethernet buffer
    Serial.print(c); //prints byte to serial monitor 
  }
 Serial.println();

  client.stop(); //stop client
}

/edit
Yes it is a float

      char *RFall;
    dtostrf(weather.total_rainfall(),4, 2, RFall);

So you have a pointer that points to who knows where, and you write some data there. Not a good idea. AT ALL.

You are telling dtostrf() to create a string that is 4 characters long, with two digits after the decimal point (so, one digit before the decimal point). Is it really that hard to figure out how big the array needs to be, and use a proper array?

all the different types of variable are driving me crazy.

It looks that there is not a small error in my code.

I was just started with the arduino without any c++ knowledge (just google examples and study them) unfortunately this project is to much for a beginner.

I will first start with http://www.cplusplus.com/doc/tutorial

Nevertheless thanks for your time and will be back soon (hopefully)

all the different types of variable are driving me crazy.

There are only 3 basic types - int, float, and char. There are unsigned and signed versions of some, and arrays of all, and differing sizes of some.

There are matching format specifiers for all types. It's just a matter of using the correct format specifier for the type of variable holding the value of interest.

Don't give up hope. Do go to that site. Do go to the library and bookstores. Learning C and C++ is good, and fun. Someday, you'll look back and not believe how much trouble you were having.