String Assignment compiler error (String Class)

So I am trying to take a String and center it on a 4X20 character LCD display. I have to admit I am not too familiar with String class, more experience with C strings.

[EDIT] I forgot to mention the compiler complains here:

case 4: // "?weatherCondition="  // Parse Weather
    //
    //weatherCondition = myText;//
    weatherCondition = centerMyString (myText);//<<<<<<<<< yes, here
    DEBUG_PRINT("Weather: ");
    DEBUG_PRINTLN(weatherCondition);
    break;

broken down… it looks like this (which works):

(How do I attach an ino file to a post?)

 void setup()  
    { 
      Serial.begin(9600);
      String myString="hello world";
      Serial.println(myString);
      Serial.println("*");
      myString = centerString(myString);
      Serial.println(myString);
    }
    void loop()      
    {
      
    }
    
    String centerString(String targetString)
    {
      if (targetString.length() > 20)
      {
        targetString = targetString.substring(0,19);
      }
      else if (targetString.length() < 19)
      {
        int numSpaces;
        numSpaces = ((20 - targetString.length())/2);
        for (int i = 0; i < numSpaces; i++)
        {
          targetString = " " + targetString;
        }
      }
      return targetString;
    }

however when I put it into my (rather large) sketch… I get this error:

...In file included from ../inc/spark_wiring.h:29:0,
from ../inc/application.h:29,
from controllerwithclasses.cpp:2:
../../core-common-lib/SPARK_Firmware_Driver/inc/config.h:12:2: warning: #warning "Defaulting to Release Build" [-Wcpp]
#warning "Defaulting to Release Build"
^
controllerwithclasses.o: In function `centerMyString(String)':
/spark/compile_server/shared/workspace/2_compile-server2/core-firmware/build/controllerwithclasses.cpp:801: undefined reference to `String::operator=(String&&)'
/spark/compile_server/shared/workspace/2_compile-server2/core-firmware/build/controllerwithclasses.cpp:812: undefined reference to `String::String(String&&)'
controllerwithclasses.o: In function `updateVariables(int, String, int, int)':
/spark/compile_server/shared/workspace/2_compile-server2/core-firmware/build/controllerwithclasses.cpp:221: undefined reference to `String::operator=(String&&)'
collect2: error: ld returned 1 exit status
make: *** [f0f3907adbe12b50d957f20903b1c9326becefada4e7c9a3b48b158f0098.elf] Error 1

Error: Could not compile. Please review your code.

full code:


// This #include statement was automatically added by the Spark IDE.
#include "PietteTech_DHT/PietteTech_DHT.h"

// This #include statement was automatically added by the Spark IDE.
#include "LiquidCrystal/LiquidCrystal.h"
//
#define DEBUG_ON
#define DISPLAY_UPDATE_TIME 3000UL
#define NUMBER_OF_MESSAGE_TYPES 17
#define NUMBER_OF_ACTIONS 5
#define DIMMER_PIN A0
#define DHTTYPE DHT11
#define DHTPIN D3
#define VERA_IP {192, 168, 1, 59}
#define VERA_PORT 3480
//
#ifdef  DEBUG_ON
#define DEBUG_PRINT(x)  Serial.print(x)
#define DEBUG_PRINTLN(x)  Serial.println(x)
#define SERIAL_START(x)  Serial.begin(x)
#else
#define DEBUG_PRINT(x)
#define DEBUG_PRINTLN(x)
#define SERIAL_START(x)
#endif
//
class httpCommand {
  String argument;
public:
  void extractValues(String);
  String mssgCommand (void) {
    return argument.substring(argument.indexOf("command#") + 8, argument.indexOf("#text="));
  }
  String mssgText (void) {
    return argument.substring(argument.indexOf("#text=") + 6, argument.indexOf("#value0="));
  }
  int mssgValue0 (void) {
    return (argument.substring(argument.indexOf("#value0=") + 8, argument.indexOf("#value1="))).toInt();
  }
  int mssgValue1 (void) {
    return (argument.substring(argument.indexOf("#value1=") + 8, argument.indexOf("?"))).toInt();
  }
};
//
void httpCommand::extractValues (String stringPassed){
  argument = stringPassed;
}
//
typedef enum {
  LCD_TIME, LCD_ALARM_STATUS, LCD_GARAGE, LCD_GUEST_GARAGE, LCD_IP_ADDRESS, \
  LCD_TEMPERATURE, LCD_AC_SETPOINT, LCD_OUTSIDE_TEMP, LCD_WEATHER, LCD_FORECAST, \
  LCD_MESSAGE, LCD_HI_LOW, LCD_EMAIL, LCD_WIND}
lcdState;
//
lcdState state = LCD_TIME;  // display starts on Time
//
//declaration
void dht_wrapper();
// must be declared before the lib initialization
// Lib instantiate
PietteTech_DHT DHT(DHTPIN, DHTTYPE, dht_wrapper);
//
int n;
//
unsigned long messageTimerStart;
unsigned long messageTimerDuration;
//
// display variables...
//
bool lightOn;
bool relayState;
bool garageOpen = false;
bool guestGarageOpen = false;
String customMessage;
String weatherCondition = "  Not Yet Reported";
String weatherForecast = "  Not Yet Reported";
String windDirection = "ZZZ";
int outdoorTemp = -99;
int outdoorHumid = -99;
int todayHigh = -99;
int todayLow = -99;
int airconSetpoint = 78;
int alarmArmed = -1;
int windSpeed = 99;
int emailCount = 99;
//
int pushButton[NUMBER_OF_ACTIONS] = {
  A3,A4,A5,A6,A7};
byte lastButtonState[NUMBER_OF_ACTIONS] = {HIGH, HIGH, HIGH, HIGH, HIGH};
//
//for  broadcasting readings from DHT
int temperature = 99;
int humidity = 49;
//
// Utility variables
//
bool messageFlag = false;
int messageSignal = 0;
byte brightLevel = 0;
byte oldBrightLevel;
//
//String incomingMessage;
//
String messageType[NUMBER_OF_MESSAGE_TYPES] = {
  "ledStatus", "alarmState", "garageState", "guestGarageState", "weatherCondition", \
  "outsideTemp", "outsideHumid", "airconSetpoint", "weatherForecast", "messageData", \
  "todayHigh", "todayLow", "windSpeed", "windDirection", "relayState", \
  "brightLevel", "emailCount"};
//
const String dayOfWeek[] = {
  "       Sunday","       Monday", "      Tuesday", "     Wednesday", "      Thursday", "       Friday", "      Saturday"};
//
//
LiquidCrystal lcd(D0, D1, D2, D3, D4, D5);
//
//
//char myIpString[24];
//
void setup()
{
  SERIAL_START(9600);
  DEBUG_PRINTLN("Starting...");
  lcd.begin(16,2);
  pinMode(D7,OUTPUT);
  for (byte i = 0; i < NUMBER_OF_ACTIONS; i++)
  {
    pinMode(pushButton[i], INPUT_PULLUP);
  }
  Spark.function("httpRequest", httpRequest);
  Spark.variable("temperature", &temperature, INT);
  Spark.variable("humidity", &humidity, INT);
  DEBUG_PRINTLN("Requesting Vera States...");
  //startupSyncVera();
}
//
void loop()
{
  Time.zone(IsDST(Time.day(), Time.month(), Time.weekday())? -4 : -5);
  for (byte i = 0; i < NUMBER_OF_ACTIONS; i++)
  {
    byte buttonState = digitalRead(pushButton[i]);
    if(buttonState != lastButtonState[i])
    {
      DEBUG_PRINTLN();
      DEBUG_PRINT("ButtonSwitch ");
      DEBUG_PRINT(i);
      DEBUG_PRINTLN(" Pressed!!!");
      DEBUG_PRINTLN();
      //fireAction(i);
    }
    lastButtonState[i] = buttonState;
  }
  lcdUpdate();
  messageTimer();
}
//
int httpRequest(String mssgArgs)
{
  DEBUG_PRINTLN("command recieved...");
  httpCommand command;
  command.extractValues(mssgArgs);
  boolean badMessage = true;
  for (int i = 0; i < NUMBER_OF_MESSAGE_TYPES; i++)
  {
    if (command.mssgCommand().equals(messageType[i]))
    {
      DEBUG_PRINTLN("Valid Message Recieved...");
      DEBUG_PRINTLN("Message type:");
      DEBUG_PRINTLN(command.mssgCommand());
      DEBUG_PRINT("messgText = ");
      DEBUG_PRINTLN(command.mssgText());
      DEBUG_PRINT("messgValue0 = ");
      DEBUG_PRINTLN(command.mssgValue0());
      DEBUG_PRINT("messgValue1 = ");
      DEBUG_PRINTLN(command.mssgValue1());
      updateVariables(i, command.mssgText(), command.mssgValue0(), command.mssgValue1());
      badMessage = false;
    }
  }
  if (badMessage)
  {
    return -1;
  }
  else return 1;
}
//
void updateVariables(int myMessg, String myText, int val0, int val1)
{
  switch (myMessg)
  {
  case 0: // "?ledStatus="
    //
    lightOn = val0;
    //if (lightOn) lcd.backlight();
    //else lcd.noBacklight();
    digitalWrite(D7,val0);
    DEBUG_PRINT("LCD Backlight: ");
    DEBUG_PRINTLN(lightOn ? "ON" : "OFF");
    break;
  case 1: // "?alarmState="
    //
    alarmArmed = val0;
    DEBUG_PRINT("Alarm ");
    DEBUG_PRINTLN(alarmArmed ? "ON" : "OFF");
    break;
  case 2: // "?garageState="
    //
    garageOpen = val0;
    DEBUG_PRINT("Garage ");
    DEBUG_PRINTLN(garageOpen ? "Open" : "Closed");
    break;
  case 3: // "?guestGarageState="
    //
    guestGarageOpen = val0;
    DEBUG_PRINT("Guest Garage ");
    DEBUG_PRINTLN(guestGarageOpen ? "Open" : "Closed");
    break;
  case 4: // "?weatherCondition="  // Parse Weather
    //
    weatherCondition = myText;//
    weatherCondition = centerMyString (weatherCondition);
    DEBUG_PRINT("Weather: ");
    DEBUG_PRINTLN(weatherCondition);
    break;
  case 5: // "?outsideTemp="  // Parse Outside Temperature
    //
    outdoorTemp = val0;
    DEBUG_PRINT("Outdoor Temp: ");
    DEBUG_PRINTLN(outdoorTemp);
    break;
  case 6: // "?outsideHumid=" // Parse Outside Humidity
    //
    outdoorHumid = val0;
    DEBUG_PRINT("Outdoor Humid: ");
    DEBUG_PRINTLN(outdoorHumid);
    break;
  case 7: // "?airconSetpoint="  // Parse A/C Setpoint
    //
    airconSetpoint = val0;
    DEBUG_PRINT("Climate Control: ");
    DEBUG_PRINTLN(airconSetpoint);
    break;
  case 8: // "?weatherForecast="  // Parse the weather forecast
    //
    weatherForecast = myText;
    DEBUG_PRINT("length of message:");
    DEBUG_PRINTLN(myText.length());//
    DEBUG_PRINT("Forecast: ");
    DEBUG_PRINTLN(weatherForecast);
    break;
  case 9: //"?messageData="  // Parse display message
    //
    customMessage = myText;
    messageTimerDuration = val0;
    messageSignal = val1;
    //centerText(customMessage);
    messageTimerStart = millis();
    messageFlag = true;
    break;
  case 10: // "?todayHigh="  // Parse Outside High Temperature
    //
    todayHigh = val0;
    DEBUG_PRINT("Today's high: ");
    DEBUG_PRINTLN(todayHigh);
    break;
  case 11: // "?todayLow="  // Parse Outside Low Temperature
    //
    todayLow = val0;
    DEBUG_PRINT("Today's low: ");
    DEBUG_PRINTLN(todayLow);
    break;
  case 12: // "?windSpeed="  // Parse Outside Low Temperature
    //
    windSpeed = val0;
    DEBUG_PRINT("Windspeed: ");
    DEBUG_PRINTLN(windSpeed);
    break;
  case 13: // "?windDirection"  // Parse Outside Low Temperature
    //
    windDirection = myText;
    DEBUG_PRINT("Wind Direction: ");
    DEBUG_PRINTLN("windDirection");
    break;
    //
  case 14:  //  "?relayState=" // Get the state of the relay
    //
    relayState = val0;
    DEBUG_PRINT("Relay is: ");
    DEBUG_PRINTLN(relayState? "1" : "0");
    break;
    //
  case 15:  //  "?brightLevel=" // Get the brightness of the LED
    //
    brightLevel = val0;
    brightLevel = map(brightLevel, 0, 100, 0, 255);
    DEBUG_PRINT(F("Brite:"));
    DEBUG_PRINTLN(brightLevel);
    if (brightLevel != oldBrightLevel)
    {
      analogWrite(DIMMER_PIN, brightLevel);
    }
    oldBrightLevel = brightLevel;
    break;
    //
  case 16: // "?emailCount"  // Parse email count
    //
    emailCount = val0;
    DEBUG_PRINT("Email Count: ");
    DEBUG_PRINTLN(emailCount);
    break;
  default:
    {
      //Nothing to do here....
    }
  }
}
void lcdUpdate()
{
  static unsigned long lastDisplayChangeTime = millis();
  if (millis() - lastDisplayChangeTime >= DISPLAY_UPDATE_TIME)
  {
    DEBUG_PRINTLN(Time.timeStr());
    DEBUG_PRINTLN(state);
    switch (state)
    {
    case LCD_TIME:
      lcdPaintBackground();
      lcd.setCursor(0,1);
      lcd.print(dayOfWeek[Time.weekday() - 1]);
      DEBUG_PRINTLN(dayOfWeek[Time.weekday() - 1]);
      if (emailCount < 0)
        state = LCD_EMAIL;
      else
        state = LCD_ALARM_STATUS;
      break;
      //
    case LCD_EMAIL:
      lcdPaintBackground();
      lcd.setCursor(0,1);
      lcd.print("    Email Count");
      lcd.setCursor(0,2);
      lcd.print("         ");
      lcd.print(emailCount);
      DEBUG_PRINT("eMails: ");
      DEBUG_PRINTLN(emailCount);
      state = LCD_ALARM_STATUS;
      break;
      //
    case LCD_ALARM_STATUS:
      lcdPaintBackground();
      lcd.setCursor(0,1);
      lcd.print("    Alarm Status");
      DEBUG_PRINT("Alarm: ");
      lcd.setCursor(0,2);
      if (alarmArmed < 0)
      {
        lcd.print("Not Yet Reported");
        DEBUG_PRINTLN("Not Yet Reported");
      }
      else
      {
        lcd.print(alarmArmed? "        Armed" : "     Not  Armed");
        DEBUG_PRINTLN(alarmArmed ? "ARMED" : "NOT ARMED");
      }
      state = LCD_GARAGE;
      break;
      //
    case LCD_GARAGE:
      lcdPaintBackground();
      lcd.setCursor(0,1);
      lcd.print("    Main  Garage");
      DEBUG_PRINT("Garage: ");
      lcd.setCursor(0,2);
      if (garageOpen == 0)
      {
        lcd.print("       Closed");
        DEBUG_PRINTLN("Closed");
      }
      else if (garageOpen == 1)
      {
        lcd.print("        Open");
        DEBUG_PRINTLN("OPEN");
      }
      else
      {
        lcd.print("  Not Yet Reported");
        DEBUG_PRINTLN("Not Yet Reported");
      }
      state = LCD_GUEST_GARAGE;
      break;
      //
    case LCD_GUEST_GARAGE:
      lcdPaintBackground();
      lcd.setCursor(0,1);
      lcd.print("    Guest Garage");
      DEBUG_PRINT("Guest Garage: ");
      lcd.setCursor(0,2);
      if (guestGarageOpen == 0)
      {
        lcd.print("       Closed");
        DEBUG_PRINTLN("Closed");
      }
      else if (guestGarageOpen == 1)
      {
        lcd.print("        Open");
        DEBUG_PRINTLN("Open");
      }
      else
      {
        lcd.print("  Not Yet Reported");
        DEBUG_PRINTLN("Not Yet Reported");
      }
      state = LCD_TEMPERATURE;
      break;
      //
    case LCD_TEMPERATURE:
      {
        lcdPaintBackground();
        lcd.setCursor(0,1);
        lcd.print(" Temperture: ");
        //temperature = (int) (DHT.getFahrenheit());
        //humidity = (int) (DHT.getHumidity());
        lcd.print(temperature);
        DEBUG_PRINT("Inside Temp:");
        DEBUG_PRINTLN(temperature);
        lcd.print((char)223);
        lcd.print("F");
        lcd.setCursor(0,2);
        lcd.print("   Humidity: ");
        lcd.print(humidity);
        DEBUG_PRINT("Humidity:");
        DEBUG_PRINTLN(humidity);
        lcd.print('%');
      }
      state = LCD_AC_SETPOINT;
      break;
    case LCD_AC_SETPOINT:
      lcdPaintBackground();
      lcd.setCursor(0,1);
      lcd.print("    A/C Setpoint");
      lcd.setCursor(0,2);
      lcd.print("        ");
      lcd.print(airconSetpoint);
      lcd.print((char)223);
      lcd.print("F");
      DEBUG_PRINT("A/C setpoint:");
      DEBUG_PRINTLN(airconSetpoint);
      state = LCD_OUTSIDE_TEMP;
      break;
      //
    case LCD_OUTSIDE_TEMP:
      lcdPaintBackground();
      lcd.setCursor(0,1);
      lcd.print(" Outdoor Temp:");
      lcd.print(outdoorTemp);
      lcd.print((char)223);
      lcd.print("F");
      DEBUG_PRINT("Ext. Temp:");
      DEBUG_PRINTLN(outdoorTemp);
      lcd.setCursor(0,2);
      lcd.print("     Humidity:");
      DEBUG_PRINT("Humidity:");
      lcd.print (outdoorHumid);
      lcd.print('#');
      DEBUG_PRINTLN(outdoorHumid);
      state = LCD_WEATHER;
      break;
      //
    case LCD_WEATHER:
      lcdPaintBackground();
      lcd.setCursor(0,1);
      lcd.setCursor(0,1);
      lcd.print("  Today's  Weather");
      lcd.setCursor(0,2);
      lcd.print(weatherCondition);
      DEBUG_PRINT("Weather: ");
      DEBUG_PRINTLN(weatherCondition);
      state = LCD_HI_LOW;
      break;
      //
    case LCD_HI_LOW:
      lcdPaintBackground();
      lcd.setCursor(0,1);
      lcd.print("Today's High: ");
      lcd.print(todayHigh);
      lcd.print((char)223);
      lcd.print("F");
      lcd.setCursor(0,2);
      lcd.print("         Low: ");
      lcd.print (todayLow);
      lcd.print((char)223);
      lcd.print("F");
      DEBUG_PRINT("Today's High: ");
      DEBUG_PRINTLN(todayHigh);
      DEBUG_PRINT("Today's Low: ");
      DEBUG_PRINTLN(todayLow);
      if (windSpeed > 2)
      {
        state = LCD_WIND;
      }
      else
      {
        state = LCD_FORECAST;
      }
      break;
      //
    case LCD_WIND:
      lcdPaintBackground();
      lcd.setCursor(0,1);
      lcd.print("   Winds  Gusting");
      lcd.print(" ");
      lcd.setCursor(1,2);
      if (windSpeed < 10) lcd.print(" ");
      lcd.print(windSpeed);
      lcd.print(" mph from the ");
      lcd.print(windDirection);
      DEBUG_PRINT("Winds are ");
      DEBUG_PRINT(windSpeed);
      DEBUG_PRINT(" mph from the ");
      DEBUG_PRINTLN(windDirection);
      state = LCD_FORECAST;
      break;
    case LCD_FORECAST:
      lcdPaintBackground();
      lcd.setCursor(0,1);
      lcd.print("      Tomorrow");
      lcd.setCursor(0,2);
      lcd.print(weatherForecast);
      DEBUG_PRINT("Forecast: ");
      DEBUG_PRINTLN(weatherForecast);
      if (messageFlag)
        state = LCD_MESSAGE;
      else
        state = LCD_IP_ADDRESS;
      break;
      //
    case LCD_MESSAGE:
      lcdPaintBackground();
      lcd.setCursor(0,1);
      if (messageSignal == 2 && brightLevel > 0)
      {
        for (int i = 0; i < 20; i++)
        {
          digitalWrite(DIMMER_PIN, HIGH);
          delay(50);
          digitalWrite(DIMMER_PIN,LOW);
          delay(50);
        }
        analogWrite(DIMMER_PIN,brightLevel);
      }
      else if (messageSignal == 1 && brightLevel >= 20)
      {
        beepTone();
      }
      lcd.setCursor(0,1);
      lcd.print("  *** Message ***");
      lcd.setCursor(0,2);
      lcd.print(customMessage);
      DEBUG_PRINT("Message: ");
      DEBUG_PRINTLN(customMessage);
      state = LCD_IP_ADDRESS;
      break;
      //
    case LCD_IP_ADDRESS:
      lcdPaintBackground();
      lcd.setCursor(0,1);
      lcd.print("     IP Address");
      DEBUG_PRINT("IP Address: ");
      lcd.setCursor(0,2);
      lcd.print("    ");
      /*
      byte mac[6];
       WiFi.macAddress(mac);*/
      IPAddress myIp = WiFi.localIP();
      for (int i = 0; i < 4; i++)
      {
        lcd.print(myIp[i]);
        DEBUG_PRINT(myIp[i]);
        if (i < 3) 
        {
          lcd.print(".");
          DEBUG_PRINT(".");
        }
      }
      DEBUG_PRINTLN("");
      lcd.print(" ");
      state = LCD_TIME;
      break;
      //
    }
    lastDisplayChangeTime = millis();
  }
}
//
void lcdPaintBackground()
{
  // Clear Display rows 1 and 2
  for (int i = 1; i < 3; i++)
  {
    lcd.setCursor(0,i);
    for (int j = 0; j < 20; j++)
    {
      lcd.print(F(" "));
    }
  }
  // Print Time and date at top
  lcd.setCursor(0,0);
  if (Time.hourFormat12() < 10) lcd.print(" ");
  lcd.print(Time.hourFormat12());
  lcd.print(Time.minute() < 10 ? ":0" : ":");
  lcd.print(Time.minute());
  lcd.print(Time.isAM() ? "am" : "pm");
  lcd.setCursor(9,0);
  if (Time.month() < 10) lcd.print(" ");
  lcd.print(Time.month());
  lcd.print(Time.day() < 10 ? "/0" : "/");
  lcd.print(Time.day());
  lcd.print("/");
  lcd.print(Time.year());
  // Print EmailCount and Alarm Status at bottom
  lcd.setCursor(0,3);
  lcd.print(emailCount < 0? 0 : emailCount);
  if (emailCount == 1)
  {
    lcd.print(" eMail   ");
  }
  else
  {
    lcd.print(" eMails   ");
  }
  lcd.setCursor(11,3);
  if (alarmArmed != 1)
  {
    lcd.print("Not Armed");
  }
  else
  {
    lcd.print("    Armed");
  }
}
//
bool IsDST(int dayOfMonth, int month, int dayOfWeek)
{
  if (month < 3 || month > 11)
  {
    return false;
  }
  if (month > 3 && month < 11)
  {
    return true;
  }
  int previousSunday = dayOfMonth - dayOfWeek;
  //In march, we are DST if our previous sunday was on or after the 8th.
  if (month == 3)
  {
    return previousSunday >= 8;
  }
  //In november we must be before the first sunday to be dst.
  //That means the previous sunday must be before the 1st.
  return previousSunday <= 0;
}
//
void messageTimer()
{
  if (millis() - messageTimerStart >= messageTimerDuration * 60000UL)
  {
    messageFlag = false;
    //signal = 0;
  }
}
//
void beepTone()
{
  delay(1);
}
//
void dht_wrapper() 
{
  DHT.isrCallback();
}
//
void fireAction(int buttonID)
{
  DEBUG_PRINTLN("");
  DEBUG_PRINTLN("Connecting to Vera...");
  byte veraIpAddress[] = VERA_IP;
  TCPClient myVera;
  if (myVera.connect(veraIpAddress, VERA_PORT)) //starts client connection, checks for connection
  { 
    switch (buttonID)
    {
    case 0:  // adjust backlight brightness down
      {
        int brite = brightLevel;
        brite -= 25;
        if (brite < 0) brite = 0;
        myVera.print(F("GET /data_request?"
          "id=action&output_format=xml"
          "&DeviceNum=111"
          "&serviceId=urn:upnp-org:"
          "serviceId:Dimmer1"
          "&action=SetTarget"
          "&newTargetValue="));
        myVera.println(brite);
        //
        break;
      }
    case 1:  // adjust backlight brightness up
      {
        int brite = brightLevel;
        brite += 25;
        if (brite > 255) brite = 255;
        myVera.print(F("GET /data_request?"
          "id=action&output_format=xml"
          "&DeviceNum=111"
          "&serviceId=urn:upnp-org:"
          "serviceId:Dimmer1"
          "&action=SetTarget"
          "&newTargetValue="));
        myVera.println(brite);
        //
        break;
      }
    case 2:  // Toggle Alarm
      //
      myVera.print(F("GET /data_request?"
        "id=action&output_format=xml"
        "&DeviceNum=112" 
        "&serviceId=urn:upnp-org:"
        "serviceId:SwitchPower1"
        "&action=SetTarget"
        "&newTargetValue="));
      myVera.print(relayState ? F("0") : F("1"));
      //
      break;
      //
    case 3:  // run lights out scene  //<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
      //
      myVera.print(F("GET /data_request?"
        "id=action&output_format=xml"
        "&DeviceNum=112"
        "&serviceId=urn:upnp-org:"
        "serviceId:SwitchPower1"
        "&action=SetTarget"
        "&newTargetValue="));
      myVera.print(relayState ? F("0") : F("1"));
      //
      break;
      //
    case 4:  // Lower Air Conditioning //<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
      //
      myVera.print(F("GET /data_request?"
        "id=action&output_format=xml"
        "&DeviceNum=112"
        "&serviceId=urn:upnp-org:"
        "serviceId:SwitchPower1"
        "&action=SetTarget"
        "&newTargetValue="));
      if (airconSetpoint > 72) myVera.print(airconSetpoint - 1);
      else myVera.print(airconSetpoint - 1);
      //
      break;
      //
    default:
      {
        //nothing to do here...
      }
    }
    myVera.println(F("Connection: close"));  //close 1.1 persistent connection  
    myVera.println(); //end of get request
    delay(1);
    myVera.flush();
    myVera.stop();
  }
}
//
void startupSyncVera() // RUNS A VERA SCENE ON STARTUP... Push the dimmer value from this scene
{
  DEBUG_PRINTLN("");
  DEBUG_PRINTLN("Connecting to Vera...");
  byte veraIpAddress[] = VERA_IP;
  TCPClient myVera;
  //myVera.connect(veraIpAddress, VERA_PORT);
  //if(myVera.connected())
  if (myVera.connect(veraIpAddress, VERA_PORT)) //starts client connection, checks for connection
  {  
    DEBUG_PRINTLN(F("asking for dimmer level"));
    myVera.println(F("GET /data_request?id=action&output_format=xml&serviceId=urn:micasaverde-com:serviceId:HomeAutomationGateway1&action=RunScene&SceneNum=40"
      " HTTP/1.1"));
    myVera.println(F("Connection: close"));  //close 1.1 persistent connection  
    myVera.println(); //end of get request
    delay(1);
    myVera.flush();
    myVera.stop();
  }
}
String centerMyString(String targetString)
{
  if (targetString.length() > 20)
  {
    targetString = targetString.substring(0,19);
  }
  else if (targetString.length() < 19)
  {
    int numSpaces;
    numSpaces = ((20 - targetString.length())/2);
    for (int i = 0; i < numSpaces; i++)
    {
      targetString = " " + targetString;
    }
  }
  return targetString;
}

I’ve edited your post to properly format the code. Please check out this post, so you know how to do this yourself in the future. Thanks in advance! ~Jordy

@BulldogLowell, this is still a bit of a problem with the String class which doesn’t have an assignment operator that does take a String object as input.
So instead of doing myString = centerString(myString); you could try myString = "" + centerString(myString);.
This should get rid of this error

But if you prefere C strings, you can still use them and for centering a string on your display you could also use lcd.setCursor(xOffset, 0); rather than padding your string with blanks.

Thanks! I’ll mess around with those options. I thought that since the Spark functions are already relying on the String class, it’s no extra overhead, so why not use Strings instead of strings. In the world of AVRs like arduino, I’m programmed (bad pun) to avoid String class like ebola.

I hadn’t used the setcursor() method because generally I’m wiping old data off the display… Are you saying use the function lcd.clear first and then center with the offset? I don’t like the blocking code in the clear() so I’ve stayed away from that method.

I’ll let you know if I can work it out with Strings…

Again, I appreciate your help.

Jim

I must admit I haven’t looked at your full code but only at the centerString snippet and since you don’t seem to append any blanks to the end of your centered string, I thought you must do some lcd.clear() anyhow.
So setCursor would have worked just fine :wink:

As for the Spark String class there are some quirks that I personally don’t like (e.g. “unpredictable” heap allocation/freeing causing fragmentation, that lack of the most likely needed assignment operator, …), so I rather use C strings after all - there I at least know exactly what’s happening behind the scenes.

hehe

I didn’t get that far, tripping over Strings…

couldn’t get this cranking either…

myString = "" + centerString(myString);

What error messages do you still get?

I guess the compiler would still complain about this line because of the same reason as above.

yeah, same error error

and I didn’t even think to look at that bit.

I finally just took your setcursor() advice:

offset = (20 - weatherCondition.length()) / 2;
lcd.setCursor(offset,2);

and just painted spaces in a prior function call.

I’ll save String class assignments for another day or go back to C string World where I can speak the language. My original arduino code was all strings, but I thought I would take my new Spark Core as an opportunity to learn Strings.

Sometimes I mistake my stubborn nature for a strong desire to learn!

Thanks Jordy for the advice… NICE forum feature!!!

That’s a courageous endevour :wink:
But to really grasp all its depths and pitfalls you might like to get your hands dirty with this
https://github.com/spark/firmware/blob/master/src/spark_wiring_string.cpp

1 Like

Just a note to say that the cause of this has been identified. The bugfix is available when building against a Photon in the Web IDE. To allow for testing, we are delaying the release of 0.4.0 to the Core a little.

1 Like