Extracting IP address from a character array returned by ESP8266 module

Many thanks for the input, you have all been very helpful and gentle on me

I have now it working, updating the LCD display and updating thingspeak every thirty seconds

It compiles OK and runs fine on a nano although is getting short of RAM, the compiler advises....

Sketch uses 13,656 bytes (44%) of program storage space. Maximum is 30,720 bytes.
Global variables use 1,587 bytes (77%) of dynamic memory, leaving 461 bytes for local variables. Maximum is 2,048 bytes.

I also get one warning for the whole sketch, as below..
warning: deprecated conversion from string constant to 'char*' [-Wwrite-strings]

scantext("IP",clientip);

I have posted the code below. Does anyone have any input which would make it better and/or free up some memory please?

I have had to split across posts as otherwise I get a warning that my post exceeds 9000 characters.

Deeclarations, setup and loop here...

#include <AltSoftSerial.h>                            // ESP8266 comms
#include "EmonLib.h"                                  // energy monitoring functions
#include <Wire.h>                                     // for I2C functionality
#include <LiquidCrystal_I2C.h>                        // LCD display functions (over I2C)

//config data - all constants 
const byte halfwaves= 20;                             // number of zero-crossings to monitor
const int  timeout  = 2000;                           // timeout (in ms) if nothing received from CTs
const int  baudrate = 9600;                           // serial monitor and ESP8266 comms
const int  tsupdate = 30000;                          // interval to update thingspeak (in ms)
const byte voltspin = 0, pvpin = 1;                   // analogue pins for volt & current sensors
const byte mainspin = 2, heaterpin = 3;

//calibration data for each input. Accounts for variations in CT outputs and AC adaptor output
const float voltcal   = 228.00;
const float ipvcal    = 59.00;
const float imainscal = 59.00;
const float iheatercal= 55.50;
const float phaseshift= 1.50;

const float pvoffset = 0;                             // correction for pv generation (Watts)
const float mainsoffset = -100;                       // correction for import/export (Watts)
const float heateroffset = -100;                      // correction for heater reading (Watts)

const char ssid[] = "PLUSNET-CTPM";                   // wifi network ssid
const char pwd[]  = "babyb00ba";                      // wifi password

const char ip[]  = "184.106.153.149";                 // thingspeak IP address  
const char GET[] = "GET /update?key=SIL2SDM25R4JO419";// thingspeak private key

// global variables for voltage, current and power for each input plus calculated house usage
float qpv=0;
float qmains = 0;
float qheater = 0;
float housetotal = 0;

//wifi in/out strings
char incoming [100]; 
char clientip [16];

//thingspeak update variables
unsigned long oldmillis;
bool setupcomplete=false;
bool TSupdated=false;

//Objects
EnergyMonitor emonpv;                                     // Create an instance of energy monitor for PV
EnergyMonitor emonmains;                                  // Create an instance of energy monitor for mains import/export
EnergyMonitor emonheater;                                 // Create an instance of energy monitor for immersion heater diversion

AltSoftSerial wifiserial;                                 // Start up a software serial port on D8 and D9 for ESP module comms

LiquidCrystal_I2C lcd(0x3f, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);  // Set the LCD I2C address and pins on the I2C backpack

void setup() {
  
  Serial.begin(baudrate);
  wifiserial.begin(baudrate);
  lcd.begin(20,4);                                         // initialize the lcd for 20 chars 4 lines, turn on backlight
  lcdtext(2,0,"   Please wait");
  
  ESP8266command("ATE0");                                  // confirm communication with ESP8266 module
  if (ESP8266response("OK",2000))
  {
    lcdtext(1,1,"Connecting to WiFi");
    connecttowifi();                                       // now try to connect to wifi network;
    
    if(ESP8266response("OK",10000))
    {
      lcdtext(0,1,"   WiFi connected  ");
      lcdtext(0,2,"Obtaining IP address");
      ESP8266command("AT+CIFSR");                          // now request IP address and MAC address
      
      if(ESP8266response("OK",5000))
      {
        scantext("IP",clientip);
        lcdtext(0,2,"                    ");
        lcdtext(0,2,"IP = ");
        lcdtext(5,2,clientip);
    
        ESP8266command("AT+PING=\"8.8.8.8\"");              //now confirm internet connectivity by pinging 
        if(ESP8266response("OK",10000))                     //Google DNS servers
        {
          lcdtext(0,3," Internet access OK ");              //now have internet connection
          setupcomplete=true;
        }
        else
        {
          lcdtext(0,3," fail - no internet ");              //no internet connection
        }
      }
      
      else
      {
        lcdtext(0,2,"                    ");
        lcdtext(0,2," No IP - check DHCP ");                //no IP  (router issue?)
      }
    }
    else
    {
      lcdtext(0,1," Connection failed  ");                  //failed to connect to wifi
    }
  }
  else
  {
    lcdtext(0,0,"Internal comms fault");                    //no communication with ESP8266
  }

  delay(2000);                                              //keep setup/error messages on screen for 2seconds
  
  lcd.clear();                                              //opersting screen for LCD
  lcdtext(0,0,"Solar :      KW");
  lcdtext(0,1,"Import:      KW"); 
  lcdtext(0,2,"House :      KW");
  lcdtext(0,3,"Heater:      KW"); 

  //calibration of the energy monitor instances
  Serial.println(F("Calibrating Emon instances"));
  emonpv.voltage(voltspin, voltcal, phaseshift);            // Voltage: input pin, calibration, phase_shift
  emonpv.current(pvpin, ipvcal);                            // Current: input pin, calibration.
  emonmains.voltage(voltspin, voltcal, phaseshift);         // Voltage: input pin, calibration, phase_shift
  emonmains.current(mainspin, imainscal);                   // Current: input pin, calibration.
  emonheater.voltage(voltspin, voltcal, phaseshift);        // Voltage: input pin, calibration, phase_shift
  emonheater.current(heaterpin, iheatercal);                // Current: input pin, calibration.
}

void loop() {
  getenergyvalues();

  updateLCD(qpv, qmains, qheater, housetotal);
  
  // update thingspeak after first run then after every 30 seconds
  if (!TSupdated) {
    sendtothingspeak(qpv, qmains, qheater, housetotal);
    oldmillis=millis();
    TSupdated=true;
  }
  if ((millis()-oldmillis) >30000){
    sendtothingspeak(qpv, qmains, qheater, housetotal);
    oldmillis=millis();
  }
}