Socket interferes with LCD custom characters regardless of connection state

I'm using sockets to send data from my ESP32 project to my computer so I can use the data in a web server, but, for reasons I am not aware of, any time Wi-Fi is initialised, the custom characters I've made for the Wi-Fi signal strength is being interfered with. It is the only 2 characters out of the 8 custom characters I'm using to be interfered with. This has only started occurring once I added in the code for the socket connection. The characters work fine if the Wi-Fi connection times out, but if Wi-Fi is initialised, even if the socket isn't connected, its interfering with the custom character and displaying a character which I have never seen on my LCD before.

I thought it had something to do with the WiFiClient being used, but I checked the RSSI and it was at normal levels (about -40/-60).

Can someone give me a bit of help with this? My code is long-ish, but I know people always ask for the full sketch, so here it is:

// custom library
#include "Triogen.h"

// other libraries used
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <SD.h>
#include <SPI.h>
#include <FS.h>
#include <RTClib.h>
#include <WiFi.h>
#include <NTPClient.h>
#include <WiFiUdp.h>
#include <Time.h>

// pin selection using GPIO pin numbering as opposed to Arduino pin numbering
#define RED_LED 1
#define GREEN_LED 2 
#define BLUE_LED 3
#define BUZZER_TOGGLE_SWITCH 5
#define RED_ALARM 6
#define GREEN_ALARM 7
#define BUZZER_PIN 8
#define CHIP_SELECT 21

// set reset vector at address 0 - essentially does a reset on the board once called
void (*resetFunc)(void) = 0;

// lcd pin configurations
LiquidCrystal_I2C lcd(0x27, 20, 4);

// RTC variables
RTC_DS3231 rtc;
time_t now; 
struct tm myTimeInfo;

// total time that the program has ran for
// this is necessary as the duration of initialisation has to be deducted for accurate logging
unsigned long tStart = millis();
unsigned long totMillis;
int totSeconds;
int totMinutes;
int totHours;
int totDays;

// timing variables 
unsigned long lastMillis = 0;
const unsigned long SAMPLE_TM = 1250;
unsigned long tSample = totMillis + SAMPLE_TM;
const unsigned long WATER_ICON_TM = 250;
unsigned long tIcon = totMillis + WATER_ICON_TM;

// timekeeping variables
// these variables use both NTP and RTC
static int year;
static int month;
static int day;
static int hour;
static int minute;
static int second;

// day and month string arrays
char dayName[7][4] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
char monthName[12][4] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
                         "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};

// toggle alarm 
bool buzzerPinState;
bool BTstate; 
bool buzzerPinOutState;

// blink and bleep without delay
bool outputState; 

// count errors to only print error once per logging interval
uint8_t errCount = 0;

int totalErrorCount = 0;

// number of samples
uint8_t nSample = 1;

// ensure the new file functions are only ran once if the time is 00:00:00
// sometimes the initialisation process can happen so quick that it happens a few times in a second
// this variable stops this from happening
uint8_t funcPassThru = 0;

uint8_t iconNo = 1;

// SD card global variables
char DIR_NAME[9] = "/TANKLOG";
char DATA_TYPE[12] = "Water Tank";
// fileName and fullPath specified 24 bytes to avoid format overflow
char fileName[24];
char fullPath[24];
File dataFile;
bool pathExists = 0;

// NTP and WiFi variables
const char* ssid = TRIOGEN_SSID;
const char* password = TRIOGEN_PASSWORD;
const uint16_t port = 8080;
const char * host = "10.2.30.116";
const char* NTP_SERVER = "pool.ntp.org";
const long GMT_OFFSET_SEC = 0;  
const int DAYLIGHT_OFFSET_SEC = 3600;
const char* TIME_ZONE = PSTR("GMT0BST,M3.5.0/1,M10.5.0");
WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP, "pool.ntp.org", GMT_OFFSET_SEC);
byte wifiState;

// Variable to check if the socket is available to send data to
// This stops the program from delaying when no socket is available (host or WiFi unavailable)
bool socketConnectState;

// only used for water tank logging (change for any other type of data)
#include <OneWire.h>
#include <DallasTemperature.h>
#define FLOAT_SW 4
#define tempResolution 12
#define ONE_WIRE_BUS 10
OneWire oneWire(ONE_WIRE_BUS);
DeviceAddress tankTempSensor;
DallasTemperature sensors(&oneWire);
int floatValue;

// temperature variables 
static float totT1;
float aveT1;
static float tempC;

// buffers for float to string conversion for formatting data
// these buffers are used as for my board, sprintf or Serial.printf cannot use float values
char charAveT1[6];
char charTotT1[8];
char charTemp[8];

// error flags 
bool floatErrState = 0;
bool tempErrState = 0;
bool highTempErrState = 0;

// alarm icons
uint8_t SPEAKER_ICON[8]          =   {B00001, B00011, B00111, B11111, B11111, B00111, B00011, B00001};
uint8_t ALARM_ON_ICON[8]         =   {B00010, B01001, B00101, B10101, B10101, B00101, B01001, B00010};
uint8_t ALARM_OFF_ICON[8]        =   {B00000, B00000, B01010, B00100, B00100, B01010, B00000, B00000};
   
// water tank diagnostic icons 
uint8_t THERMOMETER_ICON[8]      =   {B00100, B01010, B01010, B01010, B01110, B11111, B11111, B01110};
uint8_t WATER_1_ICON[8]          =   {B00100, B00100, B01010, B01010, B10001, B10001, B10001, B01110};
uint8_t WATER_2_ICON[8]          =   {B00100, B00100, B01010, B01010, B10001, B10001, B11111, B01110};
uint8_t WATER_3_ICON[8]          =   {B00100, B00100, B01010, B01010, B10001, B11111, B11111, B01110};
uint8_t WATER_4_ICON[8]          =   {B00100, B00100, B01010, B01010, B11111, B11111, B11111, B01110};
uint8_t WATER_5_ICON[8]          =   {B00100, B00100, B01010, B01110, B11111, B11111, B11111, B01110};
uint8_t WATER_6_ICON[8]          =   {B00100, B00100, B01110, B01110, B11111, B11111, B11111, B01110};

// runtime icons  
uint8_t RUNTIME_L_ICON[8]        =   {B00001, B00000, B01001, B11101, B01001, B01000, B00100, B00011};
uint8_t RUNTIME_R_ICON[8]        =   {B11000, B00100, B00010, B00010, B11010, B00010, B00100, B11000};
  
// signal icons  
uint8_t SIGNAL_1_BAR_ICON[8]      =  {B11111, B10001, B01010, B00100, B00100, B00000, B00000, B10000};
uint8_t SIGNAL_2_BAR_ICON[8]      =  {B11111, B10001, B01010, B00100, B00100, B00000, B00100, B10100};
uint8_t SIGNAL_3_BAR_ICON[8]      =  {B11111, B10001, B01010, B00100, B00100, B00001, B00101, B10101};
uint8_t SIGNAL_4_BAR_ICON[8]      =  {B00000, B00000, B00000, B00000, B10000, B10000, B10000, B10000};
uint8_t SIGNAL_CLEAR_ICON[8]      =  {B00000, B00000, B00000, B00000, B00000, B00000, B00000, B00000};
uint8_t NO_SIGNAL_ICON[8]         =  {B00000, B00000, B10100, B01000, B10100, B00001, B00101, B10101};


// function runs if SD card or RTC is not connected
void hardwareErr() {

  analogWrite(RED_LED, 0);
  analogWrite(BLUE_LED, 0);

  while (!SD.begin() || !rtc.begin()) {
    digitalWrite(BUZZER_PIN, 1);
    analogWrite(GREEN_LED, 175);
    delay(500);
    digitalWrite(BUZZER_PIN, 0);
    analogWrite(GREEN_LED, 0);
    delay(1500);
  } // end while

  if (SD.begin(CHIP_SELECT) && rtc.begin()) {
    lcd.clear();
    resetFunc();
  } // end if
} // end hardwareErr()


// show the reason for the last reset of the ESP32
int printResetReason() {

  // isolate from last serial output using newlines
  Serial.print("\n\n\n");

  int reason = esp_reset_reason();
  Serial.printf("CPU reset reason: %d ", reason);

  switch (reason) {
    case ESP_RST_UNKNOWN: Serial.println("unknown"); break;
    case ESP_RST_POWERON: Serial.println("POWER ON RESET"); break;
    case ESP_RST_SW: Serial.println("SOFTWARE RESET"); break;
    case ESP_RST_PANIC: Serial.println("PANIC RESET"); break;
    case ESP_RST_TASK_WDT: Serial.println("TASK WDT RESET"); break;
    case ESP_RST_WDT: Serial.println("OTHER WDT RESET"); break;
    case ESP_RST_DEEPSLEEP: Serial.println("EXIT DEEP SLEEP RESET"); break;
    case ESP_RST_BROWNOUT: Serial.println("BROWNOUT RESET"); break;
    case ESP_RST_SDIO: Serial.println("SDIO RESET"); break;
  } // end switch case
  
  return (reason);
} // end printResetReason()


// print hexadecimal address of DS18B20 temperature sensor
void printAddress(DeviceAddress tankTempSensor) {

  for (uint8_t i = 0; i < 8; i++) {

    if (tankTempSensor[i] < 16) {

      Serial.print("0");
    } // end if

    Serial.print(tankTempSensor[i], HEX);
  } // end for
} // end printAddress()


// initialise pin modes
void initPinModes() {

  pinMode(BUZZER_PIN, OUTPUT);
  pinMode(BUZZER_TOGGLE_SWITCH, INPUT_PULLUP);
  pinMode(FLOAT_SW, INPUT_PULLUP);
  pinMode(RED_LED, OUTPUT);
  pinMode(GREEN_LED, OUTPUT);
  pinMode(BLUE_LED, OUTPUT);
  pinMode(RED_ALARM, OUTPUT);
  pinMode(GREEN_ALARM, OUTPUT);
} // end initPinModes()


// initialise state of digital outputs
void initGPIOstates() {

  digitalWrite(RED_LED, LOW);
  digitalWrite(GREEN_LED, HIGH);
  digitalWrite(BLUE_LED, LOW);
  digitalWrite(GREEN_ALARM, HIGH);
  digitalWrite(RED_ALARM, LOW);
} // end initGPIOstates()


// initialise LCD
void initLCD() {

  lcd.begin(20, 4);
  lcd.home();
  delay(2000);
  lcd.setBacklight(255);
  lcd.clear();
} //end initLCD()


// initialise the DS18B20 temperature sensor
void initDS18B20() {

  sensors.begin();
  sensors.setWaitForConversion(false);
  sensors.requestTemperatures();
  Serial.print("DS18B20 Address: ");
  sensors.getAddress(tankTempSensor, 0);
  printAddress(tankTempSensor); 
  Serial.print("\n");  
  sensors.setResolution(tankTempSensor, tempResolution);
} // end initDS18B20()


// initialise the SD card
void initSD() {

  SD.begin(CHIP_SELECT);
  lcd.setCursor(0, 0);
  printAll("Initialising SD...");
  delay(1000);

  if (!SD.begin()) {
    lcd.clear();
    printAll("SD card failed.");
    lcd.setCursor(0, 1);
    lcd.print("Check that the SD");
    lcd.setCursor(0, 2);
    lcd.print("is present and all");
    lcd.setCursor(0, 3);
    lcd.print("wiring is correct");
    Serial.println("Check that the SD card is mounted and all wiring and connections have been made and are correct.");
    hardwareErr();
  } // end if

  uint8_t cardType = SD.cardType();

  // if SD fails, print error message and loop into hardware error function until fixed
  if (cardType == CARD_NONE) {
    lcd.clear();
    printAll("No SD card attached");
    hardwareErr();
  } // end if

  Serial.print("SD Card Type: ");

  if (cardType == CARD_MMC) Serial.println("MMC"); 
  else if (cardType == CARD_SD) Serial.println("SDSC");
  else if (cardType == CARD_SDHC) Serial.println("SDHC");
  else Serial.println("UNKNOWN");

  uint64_t cardSize = SD.cardSize() / (1024 * 1024);
  Serial.printf("SD Card Size: %lluMB\n", cardSize);
} //end initSD()


// initialise the RTC
void initRTC() {

  lcd.setCursor(0, 1);
  printAll("Initialising RTC...");
  delay(1000);

  // if RTC fails, print error message and loop into hardware error function until fixed
  if (!rtc.begin()) {

    lcd.clear();
    printAll(F("RTC failed."));
    lcd.setCursor(0, 1);
    lcd.print("Check that the RTC");
    lcd.setCursor(0, 2);
    lcd.print("is wired and mounted");
    lcd.setCursor(0, 3);
    lcd.print("correctly.");
    Serial.println("Check that the RTC is mounted and all wiring and connections have been made and are correct");
    hardwareErr();
  } // end if

  lcd.clear();
  lcd.setCursor(0, 0);
} // end initRTC()


// initialise WiFi
void initWiFi() {

  unsigned WiFiTimeout = 30;

  Serial.print("Connecting to WiFi...");
  lcd.print("Connecting to WiFi..");
  WiFi.begin(ssid, password);

  while(WiFi.status() != WL_CONNECTED) {
    Serial.print(".");
    delay(1000);
    lcd.setCursor(0, 3);
    char WiFiTimeoutBuffer[20];
    sprintf(WiFiTimeoutBuffer, "WiFi Timeout in %02ds", WiFiTimeout);
    lcd.print(WiFiTimeoutBuffer);
    WiFiTimeout -=1;

    // ESP32 hates 0's for some reason so -2 used instead of 0 to reach 0?? This method has worked
    // If it isn't broke, don't fix it!
    if (WiFiTimeout == -2) {
      Serial.print("\nCannot connect to WiFi. time will derive from last time set on RTC and offline mode will be used instead.\n\n");
      lcd.clear();
      lcd.print("No WiFi available");
      lcd.setCursor(0,2);
      lcd.print("Offline mode will");
      lcd.setCursor(0,3);
      lcd.print("be used instead");

      wifiState = 0;

      // buzz alarm 5 times if wifi is not available
      digitalWrite(BUZZER_PIN, HIGH);
      delay(100);
      digitalWrite(BUZZER_PIN, LOW);
      delay(100);
      digitalWrite(BUZZER_PIN, HIGH);
      delay(100);
      digitalWrite(BUZZER_PIN, LOW);
      delay(100);
      digitalWrite(BUZZER_PIN, HIGH);
      delay(100);
      digitalWrite(BUZZER_PIN, LOW);
      delay(4500);

      // make time variables equal to current RTC time
      DateTime now = rtc.now();
      year = now.year();
      month = now.month();
      day = now.day();
      hour = now.hour();
      minute = now.minute();
      second = now.second();
      break;
    } // end if
  } // end while

  // only run NTP function if wifi is connected
  if (WiFi.status() == WL_CONNECTED) {
    lcd.setCursor(0, 1);
    Serial.println();
    printAll("WIFI CONNECTED");
    initNTPtime();
    initSocketClient();
    wifiState = 1;
  } // end if
} // end initWiFi()


// initialise NTP and get time (function only runs if WiFi is connected)
void initNTPtime() {

  timeClient.begin();
  timeClient.update();
  
  lcd.setCursor(0, 3);
  Serial.printf("Getting time from %s...", NTP_SERVER);
  lcd.setCursor(0, 2);
  lcd.print("Getting time from   ");
  lcd.setCursor(0, 3);
  lcd.print(NTP_SERVER);
  lcd.print("...     ");
  time(&now);
  localtime_r(&now, &myTimeInfo);
  configTime(GMT_OFFSET_SEC, DAYLIGHT_OFFSET_SEC, NTP_SERVER);

  while(!getLocalTime(&myTimeInfo)) {
    Serial.print(".");
  } // end while
  
  // if NTP time is avaiable, make time variables equal to time that has been acquired from NTP
  year   = myTimeInfo.tm_year + 1900; 
  month  = myTimeInfo.tm_mon + 1;    
  day    = myTimeInfo.tm_mday;
  hour   = myTimeInfo.tm_hour;
  minute = myTimeInfo.tm_min;
  second = myTimeInfo.tm_sec; 

  // adjust RTC time to NTP time for accurate timekeeping
  char NTPtime[70];
  rtc.adjust(DateTime(year, month, day, hour, minute, second));
  sprintf(NTPtime, "Date: %02d-%02d-%02d Time: %02d:%02d:%02d", day, month, year, hour, minute, second);
  Serial.println();
  Serial.println(NTPtime);
} // end initNTPtime()


void initSocketClient() {

  WiFiClient client;

  if(!client.connect(host, port)) {
    Serial.print("\n\nConnection to host failed\n\n");
    socketConnectState = 0;
  }

  else {
    socketConnectState = 1;
    Serial.print("\n\nSocket connected");
  }
} 


// create the file name and directory for data logging
void createFileName() {

  sprintf(fileName, "%02d-%02d-%d.txt", day, month, year - 2000);
  strlcpy(fullPath, DIR_NAME, sizeof fullPath);
  strlcat(fullPath, "/", sizeof fullPath);
  strlcat(fullPath, fileName, sizeof fullPath);
  SD.exists(fullPath) ? pathExists = 1 : pathExists = 0;
  SD.mkdir(DIR_NAME);
  Serial.printf("Full File Path: X:%s\n", fullPath);
} // end createFileName()


// first write to the file created in the SD card
void firstWrite() {

  uint8_t date = strlen(fileName)-4;
  fileName[date] = '\0';
  dataFile = SD.open(fullPath, FILE_APPEND);

  if (pathExists == 0) {
    Serial.println("File contains no data. Creating headers...");
    dataFile.printf("Date: %s | Data Type: %s\n", fileName, DATA_TYPE);
    dataFile.println("Time(s),Sw State,Temp(C)");
    dataFile.close();
  }

  else if (pathExists == 1) {
    Serial.println("File already contains data.");
  }

  Serial.print("Beginning data logging...\n\n");
  lcd.clear();
} // end first write

// all time information relevant for loop
void timeInfo() {

  // use rtc time for data logging while program loops
  DateTime now = rtc.now();
  year   = now.year(); 
  month  = now.month() - 1;
  day    = now.day();
  hour   = now.hour();
  minute = now.minute();
  second = now.second();

  int DoW = now.dayOfTheWeek();
  int formattedHour = hour;

  lcd.setCursor(18, 1);

  // format time from 24 hour to 12 hour time for LCD readability
  switch(hour) {
    case 0: formattedHour = hour + 12; lcd.print("am"); break;
    case 1 ... 11: formattedHour = hour; lcd.print("am"); break;
    case 12: formattedHour = hour; lcd.print("pm"); break;
    case 13 ... 23: formattedHour = hour - 12; lcd.print("pm"); break;
  } // end switch case

  lcd.setCursor(6, 1);

  // add ordinal indicator suffixes to date for LCD readability
  switch(day) {
    case 1: case 21: case 31: lcd.print("st"); break;
    case 2: case 22: lcd.print("nd"); break;
    case 3: case 23: lcd.print("rd"); break;
    case 4 ... 20: case 24 ... 30: lcd.print("th"); break;
  } // end switch case

  // LCD time buffers
  char runtime[24];
  char DoWday[8];
  char monthTime[16];

  // if RTC fails, loop into hardware error function until it is connected
  if (!rtc.begin()) {
    lcd.clear();
    printAll(F("RTC failed"));
    hardwareErr();
  } // end if
  
  // create new file if a new day occurs 
  if (hour == 0 && minute == 0 && second == 0 && funcPassThru <= 1) {
    funcPassThru += 1;
    createFileName();
    firstWrite();
  } //end if

  sprintf(DoWday, "%s %02d", dayName[DoW], day);
  sprintf(monthTime, "%s %2d:%02d", monthName[month], formattedHour, minute);

  lcd.setCursor(0, 1);
  lcd.print(DoWday);

  lcd.setCursor(9, 1);
  lcd.print(monthTime);

  // total run time of datalogging
  totMillis = millis() - tStart;
  totSeconds = totMillis / 1000;
  totMinutes = totSeconds / 60;
  totHours = totMinutes / 60;
  totDays = totHours / 24;

  // compound remainders for run time variables
  totSeconds %= 60;
  totMinutes %= 60;
  totHours %= 24;
  totDays %= 8; // 7 days for a week + 1 so the program resets each week

  //character buffers for time variables
  char charDays[2];
  char charHours[3];
  char charMinutes[3];
  char charSeconds[3];

  // these values are converted to formatted strings as float values
  // cannot be used in sprintf for my board (Arduino Nano ESP32)
  dtostrf(totDays, 1, 0, charDays);
  dtostrf(totHours, 2, 0, charHours);
  dtostrf(totMinutes, 2, 0, charMinutes);
  dtostrf(totSeconds, 2, 0, charSeconds);

  sprintf(runtime, "%dd%2dh%2dm%2ds", totDays, totHours, totMinutes, totSeconds);
  lcd.setCursor(2, 0);
  lcd.print(runtime);

  // if run time is over a week, reset the program
  if (totDays >= 7) {
    resetFunc();
  } // end if

  // reset function pass through variable
  funcPassThru = 0;
} // end timeInfo()


// create and write custom characters for LCD 
void customChars() {

  // changes the alarm icon that is displayed whenever the alarm is on of off
  if (buzzerPinOutState == 1) {
    lcd.createChar(3, ALARM_ON_ICON);
  } // end if

  else if (buzzerPinOutState == 0) {
    lcd.createChar(3, ALARM_OFF_ICON);
  } // end else if

  // change water icon 
  if (totMillis > tIcon) {
    iconNo += 1;
    tIcon += WATER_ICON_TM;
  } // end if

  // switch case statement for water icons
  if (floatValue >= 1500 && floatValue <= 2600) {
    switch(iconNo) {
      case 1: lcd.createChar(4, WATER_1_ICON); break;
      case 2: lcd.createChar(4, WATER_2_ICON); break;
      case 3: lcd.createChar(4, WATER_3_ICON); break;
      case 4: lcd.createChar(4, WATER_4_ICON); break;
      case 5: lcd.createChar(4, WATER_5_ICON); break;
      case 6: lcd.createChar(4, WATER_6_ICON); break;
    } // end switch case

    // reset water icon 
    if (iconNo > 6) {
      iconNo = 1;
    } // end if
  } // end if

  else {
    lcd.createChar(4, WATER_6_ICON);
  } // end else

  int signalStrength = WiFi.RSSI();

  Serial.println(signalStrength);

  // print no signal icon if wifi is not connected
  if (WiFi.status() != WL_CONNECTED) {
    wifiState = 0;
    lcd.createChar(6, NO_SIGNAL_ICON);
    lcd.createChar(7, SIGNAL_4_BAR_ICON);
  } // end if

  else if (WiFi.status() == WL_CONNECTED) wifiState = 1;

  // switch case statements are causing errors in the writing of these characters,
  // therefore else if statements are being used instead
  else if (signalStrength <= -90) {
    lcd.createChar(6, SIGNAL_1_BAR_ICON);
    lcd.createChar(7, SIGNAL_CLEAR_ICON);
  } // end else if

  else if (signalStrength >= -89 && signalStrength <= -80) {
    lcd.createChar(6, SIGNAL_2_BAR_ICON);
    lcd.createChar(7, SIGNAL_CLEAR_ICON);
  } // end else if

  else if (signalStrength >= -79 && signalStrength <= -70) {
    lcd.createChar(6, SIGNAL_3_BAR_ICON);
    lcd.createChar(7, SIGNAL_CLEAR_ICON);
  } // end else if

  else if (signalStrength >= -69) {
    lcd.createChar(6, SIGNAL_3_BAR_ICON);
    lcd.createChar(7, SIGNAL_4_BAR_ICON);
  } // end else if

  lcd.createChar(0, SPEAKER_ICON);
  lcd.createChar(1, RUNTIME_L_ICON);
  lcd.createChar(2, RUNTIME_R_ICON);
  // character 3 is dynamic and dependent on the condition of the alarm state
  // character 4 is dynamic and dependent on the coniditon of the water icon time 
  lcd.createChar(5, THERMOMETER_ICON);
  // character 6 is dynamic and dependent on the condition of the signal strength
  // character 7 is dynamic and dependent on the condition of the signal strength

  // write characters to LCD
  lcd.setCursor(14, 0);
  lcd.write(0);
  lcd.setCursor(0, 0);
  lcd.write(1);
  lcd.setCursor(1, 0);
  lcd.write(2);
  lcd.setCursor(15, 0);
  lcd.write(3);
  lcd.setCursor(0, 3);
  lcd.write(4);
  lcd.setCursor(0, 2);
  lcd.write(5);
  lcd.setCursor(17, 0);
  lcd.write(6);
  lcd.setCursor(18, 0);
  lcd.write(7);
} // end customChars()


//all relevant code for alarm, as well as button debouncing
void alarmFunc() {
  
  static bool lastBTstate = 0;
  unsigned long lastDebounceTime = 0;
  const uint8_t DEBOUNCE_DELAY = 50;
  bool newBTstate = digitalRead(BUZZER_TOGGLE_SWITCH);

  if (newBTstate != lastBTstate) {
    lastDebounceTime = totMillis;
  } // end if

  if ((totMillis - lastDebounceTime) > DEBOUNCE_DELAY) {

    if (newBTstate != BTstate) {
      BTstate = newBTstate;

      if (BTstate == 1) {
        buzzerPinState = !buzzerPinState;
      } // end if
    } // end if
  } // end if

  lcd.setCursor(7, 0);

  if (buzzerPinState == 1) {
    buzzerPinOutState = 1;
   
    digitalWrite(RED_ALARM, LOW);
    digitalWrite(GREEN_ALARM, HIGH);
  } // end if

  else if (buzzerPinState == 0) {
    buzzerPinOutState = 0;
   
    digitalWrite(GREEN_ALARM, LOW);
    digitalWrite(RED_ALARM, HIGH);
  } // end else if

  lastBTstate = newBTstate;
} // end alarmFunc()


// check the temperature and float error states 
void checkForErrs() {

  // time intervals for all possible error states
  const int FLOAT_SW_TM = 500;
  const int HIGH_TEMP_TM = 750;
  const int TEMP_ERR_TM = 1000;
  const int TEMP_FLOAT_ERR_TM = 250;
  const int HIGH_TEMP_FLOAT_ERR_TM = 125;

  if (totalErrorCount >= 1) {
    lcd.setCursor(19, 0);
    lcd.print("*");
  } // end if
  
  // if float switch is "NOT OK"
  if (floatErrState == 1 && tempErrState == 0 && highTempErrState == 0) {

    if (totMillis - lastMillis >= FLOAT_SW_TM) {
      lastMillis = totMillis;

      if (outputState == 0) {
        outputState = 1;
      } // end if

      else {
        outputState = 0;
      } // end else
    } //end if

    if (buzzerPinOutState == 1) {
      digitalWrite(BUZZER_PIN, outputState);
    } // end if

    else {
      digitalWrite(BUZZER_PIN, 0);
    } // end else
      
    if (outputState == 1) {
      analogWrite(RED_LED, 0);
      analogWrite(GREEN_LED, 0);
    } // end if

    analogWrite(BLUE_LED, outputState * 255);
  } // end if

  // if a temperature error occurs (-127 or 85)
  if (tempErrState == 1 && floatErrState == 0) {

    if (totMillis - lastMillis >= TEMP_ERR_TM) {
      lastMillis = totMillis;

      if (outputState == 0) {
        outputState = 1;
      } // end if

      else {
        outputState = 0;
      } // end else
    } // end if

    if (buzzerPinOutState == 1) {
      digitalWrite(BUZZER_PIN, outputState);
    } // end if

    else {
      digitalWrite(BUZZER_PIN, 0);
    } // end else

    analogWrite(RED_LED, outputState * 255);
    analogWrite(GREEN_LED, outputState * 255);
    analogWrite(BLUE_LED, outputState * 255);

    if (errCount < 1) {
      dataFile = SD.open(fullPath, FILE_APPEND);
      dataFile.print("ERROR:");
      dataFile.close();
      Serial.print("ERROR: ");
      errCount+=1;
    } // end if
  } // end if

  // if the temperature is very high and the water level is OK
  if (highTempErrState == 1 && floatErrState == 0) {
    lcd.setCursor(12, 1);


    if (totMillis - lastMillis >= HIGH_TEMP_TM) {
      lastMillis = totMillis;

      if (outputState == 0) {
        outputState = 1;
      } // end if 

      else {
        outputState = 0;
      } // end else
    } // end if

    if (buzzerPinOutState == 1) {
      digitalWrite(BUZZER_PIN, outputState);
    } // end if

    else {
      digitalWrite(BUZZER_PIN, 0);
    } // end else

    if (outputState == 1) {
      analogWrite(GREEN_LED, 0);
      analogWrite(BLUE_LED, 0);
    } // end if

    analogWrite(RED_LED, outputState * 255);
  } // end if

  // float error and temperature error
  if (floatErrState == 1 && tempErrState == 1) {
    
    if (totMillis - lastMillis >= TEMP_FLOAT_ERR_TM) {
      lastMillis = totMillis;

      if (outputState == 0) {
        outputState = 1;
      } // end if

      else {
        outputState = 0;
      } // end else
    } // end if

    if (buzzerPinOutState == 1) {
      digitalWrite(BUZZER_PIN, outputState);
    } // end if

    else {
      digitalWrite(BUZZER_PIN, 0);
    } // end else

    // flash blue for float error
    analogWrite(BLUE_LED, 255);

    // then flash white for temperature error
    analogWrite(RED_LED, outputState * 255);
    analogWrite(GREEN_LED, outputState * 255);
  } // end if

  // float error and high temperature
  if (floatErrState == 1 && highTempErrState == 1) {

    if (totMillis - lastMillis >= HIGH_TEMP_FLOAT_ERR_TM) {
      lastMillis = totMillis;

      if (outputState == 0) {
        outputState = 1;
      } // end if

      else {
        outputState = 0;
      } // end else
    } // end if

    if (buzzerPinOutState == 1) {
      digitalWrite(BUZZER_PIN, outputState);
    } // end if

    else {
      digitalWrite(BUZZER_PIN, 0);
    } // end else
    
    analogWrite(BLUE_LED, outputState * 255);
    analogWrite(RED_LED, !outputState * 255); 
  } // end if

  // changes the output state to 0 and sends a low signal to buzzer to ensure hardware isn't stuck
  // in a constant error state (e.g. buzzer HIGH or RGB LED constant BLUE_LED)
  if (floatErrState == 0 && tempErrState == 0 && highTempErrState == 0) {
    outputState = 0;
    digitalWrite(BUZZER_PIN, 0);
  } // end if
} // end checkForErrs()


// check the state of the float switch to check if the water tank is over flowing
void checkFloatState() {

  lcd.setCursor(2, 3);

  floatValue = analogRead(FLOAT_SW);
  static int floatSmoothingError = 0;

  if (floatValue >= 500 && floatValue <= 4000) {
    lcd.print("WATER LEVEL OK    ");
    floatErrState = 0;
    floatSmoothingError = 0;
  } // end if
  
  else if (floatValue < 500) {
    lcd.print("WATER LEVEL HIGH");
    floatErrState = 1;
    floatSmoothingError = 0;
  } // end else if

  else if (floatValue > 4000) {
    floatSmoothingError += 1;
  } // end else if

  if (floatSmoothingError >= 2) {
    lcd.print("NO SWITCH FOUND ");
    floatErrState = 1;
    totalErrorCount += 1;
  } // end if

  Serial.println(floatValue);
} // end checkFloatState()


// check the temperature of the water tank to ensure the water is not too hot for cooling
void checkTemp() {

  // if temperature is a valid value
  if (tempC >-127 && tempC < 85) {
    lcd.setCursor(2, 2);
    lcd.print(tempC);
    lcd.print("\337C           ");
    tempErrState = 0;
  } // end if

  // so temperature values can be used in a switch case statement (easier for code readability)
  int intTemp = floor(tempC);
  
  switch(intTemp) {

    case -127:
      tempErrState = 1;
      lcd.setCursor(2, 2);
      lcd.print("NO SENSOR FOUND   ");
      break;
      
    case 4 ... 25:  

      if (outputState == 0) {
        analogWrite(RED_LED, 0);   
        analogWrite(GREEN_LED, 255); 
        analogWrite(BLUE_LED, 0); 
      } // end if

      highTempErrState = 0;
    break;

    case 26 ... 28: 

      if (outputState == 0) {
        analogWrite(RED_LED, 255);
        analogWrite(GREEN_LED, 255);
        analogWrite(BLUE_LED, 0); 
      } // end if

      highTempErrState = 0;
    break;

    case 29 ... 31: 

      if (outputState == 0) {
        analogWrite(RED_LED, 255);
        analogWrite(GREEN_LED, 70);
        analogWrite(BLUE_LED, 0);
      } // end if

      highTempErrState = 0;
    break;

    case 32 ... 34:
      if (outputState == 0) {
        analogWrite(RED_LED, 255);
        analogWrite(GREEN_LED, 0);
        analogWrite(BLUE_LED, 0);
      } // end if

      highTempErrState = 0;
    break;

    case 35 ... 84: 
      highTempErrState = 1;
    break;

    case 85:
      tempErrState = 1;
      lcd.setCursor(2, 2);
      lcd.print("CONVERSION ERROR  ");
      break;
  } // end switch case 
} // end checkTemp()


// sample the data 
void sampleData() {

  // store temperature in a float variable
  tempC = sensors.getTempCByIndex(0);

  char sampleData[150];

  // sample data within the sampling interval
  if (totMillis > tSample) {
    totT1 = tempC + totT1;
    aveT1 = totT1 / nSample;
    dtostrf(aveT1, 5, 2, charAveT1);
    dtostrf(totT1, 7, 2, charTotT1);
    dtostrf(tempC, 7, 2, charTemp);
    sprintf(sampleData, "Time: %02d:%02d:%02d | Runtime: %02dd %02dh %02dm %02ds | Sample: %d | Sw: %d | temp(°C):%s | Ave:  %s | Tot:%s\n",
    hour, minute, second, totDays, totHours, totMinutes, totSeconds,
    nSample, !floatErrState, charTemp, charAveT1, charTotT1);
    Serial.print(sampleData);
    nSample +=1;
    tSample += SAMPLE_TM;
    sensors.requestTemperatures();
  } // end if

  aveT1 = totT1 / nSample;
} // end sampleData()


// log the data
void logSocketData() {

  WiFiClient client;

  if(WiFi.status() == WL_CONNECTED && socketConnectState == 1) {

    if(!client.connect(host, port)) {
      Serial.print("\n\nConnection to host failed\n\n");
    }
  }

  // converts the time of day to seconds for the logging file
  unsigned long hToM = hour * 60;
  unsigned long hToS = hToM * 60;
  unsigned long mToS = (minute * 60);
  unsigned long sToS = second;
  unsigned long tmDayInS = hToS + mToS + sToS;

  char data[20];
  char charTmDayInS[7];
  dtostrf(tmDayInS, 5, 0, charTmDayInS);
  sprintf(data, "%s,%d,%s", charTmDayInS, !floatErrState, charAveT1);

  dataFile = SD.open(fullPath, FILE_APPEND);

  if (!dataFile) {
    lcd.clear();
    printAll(F("File write Err"));
    hardwareErr();
  } // end if

  static int logCount = 0;

  if (nSample == 9) {
    nSample -=1;
    dataFile.println(data);
    dataFile.close();

    if(wifiState == 1 && socketConnectState == 1) {
      client.print(data);
      client.stop();
    }

    logCount+=1;
    Serial.printf("\n LOG NO.%d\n", logCount);
    Serial.println("| Time(s) | Float Switch State | Average Temperature(°C) |");
    Serial.printf("|  %s  |         %d          |          %s          |\n\n",
    charTmDayInS, !floatErrState, charAveT1);
    totT1 = 0;
    nSample = 1;
    errCount = 0;
  } // end if
} // end logData()


// setup function
void setup() {

  Wire.begin();
  Serial.begin(BAUD);
  delay(1500); 
  Wire.setClock(400000);

  printResetReason();
  initPinModes();
  initGPIOstates();
  initLCD();
  initDS18B20();
  initSD();
  initRTC();
  initWiFi();
  createFileName();
  firstWrite();

  tStart = millis();
} // end setup()


// loop function
void loop() {

  timeInfo();
  customChars();
  alarmFunc();
  checkForErrs();
  checkFloatState();
  checkTemp();
  sampleData();
  logSocketData();
} // end loop()

// END OF PROGRAM

Your logic seems wrong here:

  if (WiFi.status() != WL_CONNECTED) {
    wifiState = 0;
    lcd.createChar(6, NO_SIGNAL_ICON);
    lcd.createChar(7, SIGNAL_4_BAR_ICON);
  } // end if

  else if (WiFi.status() == WL_CONNECTED) wifiState = 1;

  // switch case statements are causing errors in the writing of these characters,
  // therefore else if statements are being used instead
  else if (signalStrength <= -90) {
    lcd.createChar(6, SIGNAL_1_BAR_ICON);
...

if Wifi.status() is not connected, you create no signal icons.
your else if() statement then tests wifi.status() again

you contine with else if() statements so if wifi is connected, only the first else if() statement gets executed, none of the following else if() statements that set the signal strength icons.

It seems like the logic should be

  if (WiFi.status() != WL_CONNECTED) {
    wifiState = 0;
    lcd.createChar(6, NO_SIGNAL_ICON);
    lcd.createChar(7, SIGNAL_4_BAR_ICON);
  }
  else if (WiFi.status() == WL_CONNECTED)
  {
    wifiState = 1;

    if (signalStrength <= -90) {
      lcd.createChar(6, SIGNAL_1_BAR_ICON);
      lcd.createChar(7, SIGNAL_CLEAR_ICON);
    }
    else if (signalStrength >= -89 && signalStrength <= -80) {
      lcd.createChar(6, SIGNAL_2_BAR_ICON);
      lcd.createChar(7, SIGNAL_CLEAR_ICON);
    }
    else if (signalStrength >= -79 && signalStrength <= -70) {
      lcd.createChar(6, SIGNAL_3_BAR_ICON);
      lcd.createChar(7, SIGNAL_CLEAR_ICON);
    }
    else if (signalStrength >= -69) {
      lcd.createChar(6, SIGNAL_3_BAR_ICON);
      lcd.createChar(7, SIGNAL_4_BAR_ICON);
    }
  }
 ...

Its not clear what you mean by your icons are messed up.... maybe a photo?

That fixed it! I'm not sure how I missed that. Thank you!