//Code developed by Chris Gimson chris@gimson.co.uk
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
String Firmware_Version = "Pool_Temperature_MQTT_1V2 11th Nov 2020";
#define SERIAL_BAUDRATE 115200
// ----------------- IO Pin assignments - Change to suit hardware build
const byte AP_Switch = 0; // IO address of the AP enable switch
const byte ONE_WIRE_BUS = 12; // pin used for Temperature sensor bus
const byte Board_SDA = 5;
const byte Board_SCL = 4;
// -------------------------- IO states - Change to suit hardware build --------------
const boolean LED_On = LOW;
const boolean LED_Off = !LED_On;
const boolean SwitchOn = LOW; // Switch/buttons
const boolean SwitchOff = !SwitchOn;
const boolean AP_SwitchOn = LOW; // IO status for AP switch ON
const boolean AP_SwitchOff = !AP_SwitchOn;
String MQTT_Broker = "MQTT-Server" ; // ------------ MQTT server Name -----------
// --------------- PCF8574 - make sure you have correct address selected depending on chip number ---
const byte Address8574 = 0x38; // address of 8574A IO chip
//const byte Address8574 = 0x20; // address of 8574 IO chip
const byte Output = 0x00; // mask for P0-7 = output
const byte MaxStringLength = 20; // Max. no of characters allowed in any stored string.
char KeyboardBuffer[MaxStringLength]; // Keyboard buffer
const unsigned long TaskTimerInterval = 1000; // Time between timed task cycle (ms)
unsigned long LoopRunningTimer; // used as timer for timed operations.
const unsigned long One_Minute_timer_Tick_Threshold = 60000; // used to determine one minute timer activity (mS)
byte Command = 255; // input buffer for main screen commands
// -------------- MUST be set if remote data transmission is enabled -----------
byte HouseNode1_OLED_ScreenNo = 1; // Screen number of HouseNode 1 that this nodes data will be sent to = 1,2,3,4 or 5
byte HouseNode2_OLED_ScreenNo = 1; // Screen number of HouseNode 2 that this nodes data will be sent to = 1,2,3,4 or 5
byte HouseNode3_OLED_ScreenNo = 1; // Screen number of HouseNode 2 that this nodes data will be sent to = 1,2,3,4 or 5
byte HouseNode4_OLED_ScreenNo = 1; // Screen number of HouseNode 2 that this nodes data will be sent to = 1,2,3,4 or 5
byte HouseNode5_OLED_ScreenNo = 1; // Screen number of HouseNode 2 that this nodes data will be sent to = 1,2,3,4 or 5
boolean RemoteDataSend1;
boolean RemoteDataSend2;
boolean RemoteDataSend3;
boolean RemoteDataSend4;
boolean RemoteDataSend5;
unsigned int LightLevel;
byte PoolTempSensorIndex;
byte AirTempSensorIndex;
boolean AccessPointRunning; // true = AP is running
byte DeepSleepInterval; // deep sleep interval in minutes
String ssid = "...................."; // variable for storing the Access Point SSID
String esid; // Variable for the WiFi Station log in SSID (stored in EEPROM)
String epass = ""; // Variable for the WiFi Station log in Password (stored in EEPROM)
String HostName = "...................." ;
String StoredString = "....................";
String passphrase = "....................";
String st;
String content;
boolean LoginSuccessfull; // = true if WiFi login failed
String user = "...................." ; // MQTT Broker user name
String MQTT_Pass = "...................." ;// MQTT Broker password
// -----------------------------------------------------------------------------------------
// EEPROM - direct byte addresses for EEPROM storage of configurable parameters
const unsigned int EEPROM_Start_Address = 0; // starting address for EEPROM store (changing this moves the EEPROM block up/down the available memory range
const unsigned int EEPROM_WiFi_SSID = EEPROM_Start_Address; // start of Wifi SSID store - 20 bytes
const unsigned int EEPROM_WiFi_Password = EEPROM_WiFi_SSID + MaxStringLength; // start of Wifi password - 20 bytes
const unsigned int EEPROM_HostName = EEPROM_WiFi_Password + MaxStringLength; // storage of Alexa output descripts - 80 bytes
const unsigned int EEPROM_EnableMessages = EEPROM_HostName + MaxStringLength; // disgnostic messages enable
const unsigned int EEPROM_Station_Address = EEPROM_EnableMessages + 1; // Station ID for remote control
const unsigned int EEPROM_DeepSleepInterval = EEPROM_Station_Address + 1;
const unsigned int EEPROM_AP_Password = EEPROM_DeepSleepInterval + 1; // Access point password 20 bytes
const unsigned int EEPROM_DarkThreshold = EEPROM_AP_Password + + MaxStringLength;
const unsigned int EEPROM_RemoteDataSend1 = EEPROM_DarkThreshold + 1;
const unsigned int EEPROM_RemoteDataSend2 = EEPROM_RemoteDataSend1 + 1;
const unsigned int EEPROM_RemoteDataSend3 = EEPROM_RemoteDataSend2+ 1;
const unsigned int EEPROM_RemoteDataSend4 = EEPROM_RemoteDataSend3 + 1;
const unsigned int EEPROM_RemoteDataSend5 = EEPROM_RemoteDataSend4 + 1;
const unsigned int EEPROM_HouseNode1_OLED_ScreenNo = EEPROM_RemoteDataSend5 + 1;
const unsigned int EEPROM_HouseNode2_OLED_ScreenNo = EEPROM_HouseNode1_OLED_ScreenNo + 1;
const unsigned int EEPROM_HouseNode3_OLED_ScreenNo = EEPROM_HouseNode2_OLED_ScreenNo + 1;
const unsigned int EEPROM_HouseNode4_OLED_ScreenNo = EEPROM_HouseNode3_OLED_ScreenNo + 1;
const unsigned int EEPROM_HouseNode5_OLED_ScreenNo = EEPROM_HouseNode4_OLED_ScreenNo + 1;
const unsigned int EEPROM_PoolTempSensorIndex = EEPROM_HouseNode5_OLED_ScreenNo + 1;
const unsigned int EEPROM_AirTempSensorIndex = EEPROM_PoolTempSensorIndex + 1;
const unsigned int EEPROM_BargraphMinimumTemperature = EEPROM_AirTempSensorIndex + 1;
const unsigned int EEPROM_RecipientHostName = EEPROM_BargraphMinimumTemperature + 1;
const unsigned int EEPROM_RecipientHostName2 = EEPROM_RecipientHostName + MaxStringLength;
const unsigned int EEPROM_RecipientHostName3 = EEPROM_RecipientHostName2 + MaxStringLength;
const unsigned int EEPROM_RecipientHostName4 = EEPROM_RecipientHostName3 + MaxStringLength;
const unsigned int EEPROM_RecipientHostName5 = EEPROM_RecipientHostName4 + MaxStringLength;
const unsigned int EEPROM_MQTT_Broker = EEPROM_RecipientHostName5 + MaxStringLength;
const unsigned int EEPROM_MQTT_MeasurementPushTopic = EEPROM_MQTT_Broker + MaxStringLength; // not used
const unsigned int EEPROM_MQTT_Enable = EEPROM_MQTT_MeasurementPushTopic + MaxStringLength;
const unsigned int EEPROM_MQTT_Format = EEPROM_MQTT_Enable + 1;
const unsigned int EEPROM_MQTT_BrokerType = EEPROM_MQTT_Format + 1;
const unsigned int EEPROM_MQTT_User = EEPROM_MQTT_BrokerType + 1;
const unsigned int EEPROM_MQTT_Pass = EEPROM_MQTT_User + MaxStringLength;
const unsigned int EEPROM_Header_Block = EEPROM_MQTT_Pass + MaxStringLength; // EEPROM header block 5 bytes
const unsigned int EEPROM_End = EEPROM_Header_Block + 5;
String RecipientHostName;
String RecipientHostName1;
String RecipientHostName2;
String RecipientHostName3;
String RecipientHostName4;
String RecipientHostName5;
byte BMP280;
float AveragePoolTemperature;
float PreviousAveragePoolTemperature;
float AirTemperature;
float AirPressure;
float HousingTemperature;
const boolean Fail = false;
const boolean Good = true;
boolean TX_SendSuccessSend1;
boolean TX_SendSuccessSend2;
boolean TX_SendSuccessSend3;
boolean TX_SendSuccessSend4;
boolean TX_SendSuccessSend5;
byte DarkThreshold; //Light threshold for day/night detection (night = LEDs turned off)
boolean EnableMessages; // true = enable diagnostic messages, false = mute messages
boolean Soft_AP_Switch; // true = Access point will run
unsigned long Time_Start; // used in boolean Check_AP_Switch(unsigned long Debounce)
// stores start time (ms) when button is pressed
const byte HAS_Compatible = 0; // MQTT messages compatible with HAS controllers
const byte MQTT_Single = 1; // Single Topic per data parameter
const byte MQTT_Compact = 2; // All data sent in one topic
byte MQTT_Format = MQTT_Compact;
const boolean Local = true; //
const boolean Cloud = !Local;
boolean MQTT_ServerType; // determins the type of MQTT server being used (Local or Cloud)
byte BargraphMinimumTemperature; // minimum Bargraph temperature thresholds
long lastMsg = 0;
char msg[50];
int value = 0;
unsigned long MQTT_PushInterval; // interval in milliseconds between each MQTT message push
unsigned long MQTT_RunningTimer;
String MQTT_BrokerCopy;
long MQTT_LastReconnectAttempt = 0;
unsigned int MQTT_DropOutCounter;
// ---------------------------------------------------------------
WiFiClient MQTT_Client;
ESP8266WebServer serverAP(80);
PubSubClient client(MQTT_Client);
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);
Adafruit_BMP085 bmp;
// ---------------------------------------------------------------
void setup()
{
Wire.begin(Board_SDA,Board_SCL);
byte i = 0;
Wire.beginTransmission(Address8574); // Address the PCF8574 chip
Wire.write(Output); // SETUP IO MASK - 1 if INPUT
Wire.endTransmission();
PortWrite(0xFF); // set all outputs OFF
// ------------------------------------------------------------
Serial.begin(SERIAL_BAUDRATE);
EEPROM.begin(800); // Enable 512 bytes of EEPROM
pinMode(AP_Switch, INPUT_PULLUP);
pinMode(ONE_WIRE_BUS,INPUT_PULLUP);
Serial.println("");
// -----------------------------------------------------------
Serial.println("");
Serial.println(Firmware_Version); // display firmware revision number
Serial.println(F("Developer: Chris Gimson chris@gimson.co.uk"));
Serial.print(F("EEPROM used = ")); Serial.println(EEPROM_End);
// -------------------- process EEPROM contents and initialise variables and flags -------------------------
Auto_EEPROM_Check(); // check to see if EEPROM is initialised, if not set to defaults
EnableMessages = EEPROM.read(EEPROM_EnableMessages); // set the display messages flag
RemoteDataSend1 = EEPROM.read(EEPROM_RemoteDataSend1);
RemoteDataSend2 = EEPROM.read(EEPROM_RemoteDataSend2);
RemoteDataSend3 = EEPROM.read(EEPROM_RemoteDataSend3);
RemoteDataSend4 = EEPROM.read(EEPROM_RemoteDataSend4);
RemoteDataSend5 = EEPROM.read(EEPROM_RemoteDataSend5);
HouseNode1_OLED_ScreenNo = EEPROM.read (EEPROM_HouseNode1_OLED_ScreenNo);
HouseNode2_OLED_ScreenNo = EEPROM.read (EEPROM_HouseNode2_OLED_ScreenNo);
HouseNode3_OLED_ScreenNo = EEPROM.read (EEPROM_HouseNode3_OLED_ScreenNo);
HouseNode4_OLED_ScreenNo = EEPROM.read (EEPROM_HouseNode4_OLED_ScreenNo);
HouseNode5_OLED_ScreenNo = EEPROM.read (EEPROM_HouseNode5_OLED_ScreenNo);
DarkThreshold = EEPROM.read(EEPROM_DarkThreshold);
DeepSleepInterval = EEPROM.read(EEPROM_DeepSleepInterval);
PoolTempSensorIndex = EEPROM.read(EEPROM_PoolTempSensorIndex);
AirTempSensorIndex = EEPROM.read(EEPROM_AirTempSensorIndex);
BargraphMinimumTemperature = EEPROM.read(EEPROM_BargraphMinimumTemperature);
DownloadMQTT_detailsFromEEPROM(EnableMessages);
if(PoolTempSensorIndex > 1 || AirTempSensorIndex > 1)
{
AirTempSensorIndex = 0;
PoolTempSensorIndex = 1;
}
Download_WiFi_Login_Details_From_EEPROM(true); // Download EEPROM values to working memory
AccessPointRunning = false;
// ---------------------------------------------------------------------
Soft_AP_Switch = false; // Access point is disabled
// -------------------------------------------------------------
serverAP.on("/OLED_ScreenSettings",OLED_ScreenSettings);
serverAP.on("/Quit",Quit);
serverAP.on("/WiFiSetup",WiFiSetup);
serverAP.on("/WiFiConfig", WiFiConfig);
serverAP.on("/", Start);
sensors.begin(); // ------- DS18B20 Temperature sensor ---------
BMP280 = 1; // look for BMP sensor
if (bmp.begin() == false) BMP280 = 0;
else
if(EnableMessages) Serial.println(F("BMP280 sensor fitted"));
LoopRunningTimer = millis(); // for the LED flash rates
MQTT_LastReconnectAttempt = 0;
MQTT_Client.setTimeout(800);
MQTT_DropOutCounter = 0;
// -------------------------------------------------------------
GetMeasurements(); // Read Temperature sensor
Bargraph_LEDs(); // update bargraph if fitted
if(EnableMessages) Demon(); // diagnostic dump all variabled
i = Check_AP_Switch();
if(i == 1) Soft_AP_Switch = true; // set flag if AP switch pressed for > 1 seconds
else WifiConnect(); // connect to wifi network if remote Tx is enabled
// -------------------------------------------------------------------------------------
} // end of Setup
// --------------------------------------------------------
void loop()
{
byte i = 0;
i = Check_AP_Switch();
if(i == 1) Soft_AP_Switch = true; // set flag if AP switch pressed for > 1 seconds
if(Soft_AP_Switch == true) // Access Point (AP) is enabled
{
if (AccessPointRunning == false) // is AP already running?
{ // not running so set up AP
Set_Up_Access_Point();
AccessPointRunning = true;
} // end of if (AccessPointRunning == false)
else serverAP.handleClient(); // AP is running so maintain AP web page
} // end of if(Soft_AP_Switch == true) // Access Point (AP)
else
{ // AP is disabled
WiFi.softAPdisconnect(true); // disconnect the AP
serverAP.stop(); // Stop the AP webserver
WiFi.mode(WIFI_STA); // Switch to station mode only
AccessPointRunning = false;
} // end of else
//if ((RemoteSendEnabled() == true || MQTT_ServerType != HAS_Compatible) && LoginSuccessfull == true)
if (LoginSuccessfull == true)
{
randomSeed(micros());
if (MQTT_ServerType == Local) MQTT_BrokerCopy = MQTT_Broker + ".local"; // Local server
else MQTT_BrokerCopy = MQTT_Broker; // cloud based server
client.setServer(MQTT_BrokerCopy.c_str(), 1883);
client.setCallback(callback);
Serial.println(F("Send Data"));
if (!client.connected())
{
long Now = millis();
if (Now - MQTT_LastReconnectAttempt > 2000)
{ // Timeout - enable attempt to reconnect
MQTT_LastReconnectAttempt = Now;
if (Reconnect()) MQTT_LastReconnectAttempt = 0;
}
} // end of if (!client.connected())
else client.loop();// Client connected
} // end of if (LoginSuccessful == true && MQTT_Enable == true)
// -------------------------------------------------------------------------------
Check_For_Keyboard_Command();
// ---------------------------------------------------------------------------------------------
// Station mode
//if (LoginSuccessfull== true && RemoteSendEnabled()== true && WiFi.status()==!WL_CONNECTED && AccessPointRunning==false)
if (LoginSuccessfull== true && WiFi.status()==!WL_CONNECTED && AccessPointRunning==false)
Reset_Device("Lost Wifi Connection"); // Lost connection (only if AP is not running)
// ------------------------ TIMED OPERATIONS --------------------
unsigned long TaskTimer = millis() - LoopRunningTimer; // Grab time value since last scan
if (TaskTimer >= TaskTimerInterval)
{
GetMeasurements(); // Read Temperature sensor
Bargraph_LEDs(); // update bargraph if fitted
// -------- REMOTE DATA TRANSMISSION TO MQTT broker
if(DarkThreshold != 1 && Soft_AP_Switch == false)
{
if (LoginSuccessfull == true && client.connected()== true) // if both Wifi & MQTT connected
{
switch (MQTT_Format) // determine what MQTT format is selected
{
case HAS_Compatible: // compatible with HAS controller
{
if(RemoteDataSend1) // if enabled, send screen data to linked Housenode 1
TX_SendSuccessSend1 = SendRemoteData(HouseNode1_OLED_ScreenNo,0);
else TX_SendSuccessSend1 = Good;
if(RemoteDataSend2) // if enabled, send screen data to linked Housenode 2
TX_SendSuccessSend2 = SendRemoteData(HouseNode2_OLED_ScreenNo,1);
else TX_SendSuccessSend2 = Good;
if(RemoteDataSend3) // if enabled, send screen data to linked Housenode 3
TX_SendSuccessSend3 = SendRemoteData(HouseNode3_OLED_ScreenNo,2);
else TX_SendSuccessSend3 = Good;
if(RemoteDataSend4) // if enabled, send screen data to linked Housenode 4
TX_SendSuccessSend4 = SendRemoteData(HouseNode4_OLED_ScreenNo,3);
else TX_SendSuccessSend4 = Good;
if(RemoteDataSend5) // if enabled, send screen data to linked Housenode 5
TX_SendSuccessSend5 = SendRemoteData(HouseNode5_OLED_ScreenNo,4);
else TX_SendSuccessSend5 = Good;
delay(1000); // wait for MQTT data to be published
break;
}// end of case HAS_Compatible:
case MQTT_Single:
{
TX_SendSuccessSend1 = SendSingleMessage(0); // send Water Temperature value
TX_SendSuccessSend2 = SendSingleMessage(1); // send Air Temperature value
TX_SendSuccessSend3 = SendSingleMessage(2); // send Air Pressure
TX_SendSuccessSend4 = Good;
TX_SendSuccessSend5 = Good;
delay(250);
break;
} // end of case MQTT_Single:
case MQTT_Compact:
{
TX_SendSuccessSend1 = SendSingleMessage(3); // Send Compact data message
TX_SendSuccessSend2 = Good;
TX_SendSuccessSend3 = Good;
TX_SendSuccessSend4 = Good;
TX_SendSuccessSend5 = Good;
delay(250);
break;
} // end of case MQTT_Single:
} // end of switch(MQTT_Format)
} // end of if (LoginSuccessfull == true && client.connected()== true) // if both Wifi & MQTT connected
} // end of if(DarkThreshold != 1 && Soft_AP_Switch == false)
LoopRunningTimer = millis(); // Set LED flash timer for ON cycle
CheckForDeepSleep();
} // end of if (TaskTimer >= TaskTimerInterval)
} // end of void loop()
// -------------------------------------------------------------------------
boolean SendSingleMessage(byte DataType)
// DataType 0 = WaterTemp, 1 = AirTemp, 2 = BaroPress, 3 = Compact data
{ // returns true = send succeeded, false = send failed
if (WiFi.status() == WL_CONNECTED) //Check WiFi connection status
{ // Compose MQTT_Packet using selected measured data data
String MQTT_Packet;
String Topic;
switch(DataType)
{
case 0:
{
Topic = "Pool/WaterTemp";
MQTT_Packet = String(AveragePoolTemperature,1);
break;
}
case 1:
{
Topic = "Pool/AirTemp";
MQTT_Packet = String(AirTemperature,1);
break;
}
case 2:
{
Topic = "Pool/BaroPress";
MQTT_Packet = String(AirPressure,1);
break;
}
case 3:
{
Topic = "Pool/";
MQTT_Packet = "{\"WaterTemp\":" + String(AveragePoolTemperature,1) + ",";
MQTT_Packet += "\"AirTemp\":" + String(AirTemperature,1) + ",";
MQTT_Packet += "\"BaroPress\":" + String(AirPressure,1) + "}";
break;
}
} // end of switch(DataType)
if(EnableMessages)
{
Serial.print(F("["));
Serial.print(Topic);
Serial.print("] ");
Serial.println(MQTT_Packet);
}
// ------------- MQTT Push message -------------------
delay(50);
if(client.publish(Topic.c_str(),MQTT_Packet.c_str()) == true) return true; // true = message sent
else // message failed to send
{
if(EnableMessages) Serial.println(F("Message Failed"));
return false;
}
} // end of if (WiFi.status() == WL_CONNECTED) //Check WiFi connection status
else return 1; // Lost Wifi so exit
} // end of boolean SendSingleMessage(byte DataType)
// ------------ MQTT ----------------------------------
void callback(char* topic, byte* payload, unsigned int length)
{
String Msg = "";
byte Counter = 0;
while (Counter < length) // create string from received message payload
{
Msg+= (char)payload[Counter];
Counter++;
}
} // end of void callback(char* topic, byte* payload, unsigned int length)
// -------------------------------------------------------------------------------
boolean Reconnect()
{
if (!client.connected())
{
Serial.print("Attempt MQTT connect...");
String clientId = "MQTT_Client-";
clientId += String(random(0xffff), HEX); // Create a random client ID
boolean Connect = false;
if(MQTT_ServerType == Cloud) // if Broker is cloud based attempt log in
Connect = client.connect(clientId.c_str(),user.c_str(),MQTT_Pass.c_str());
else Connect = client.connect(clientId.c_str()); // if local, attempt login
if(Connect == true) // if connection made
{
Serial.println("connected");
MQTT_DropOutCounter ++;
}
else // not connected
{
Serial.print("failed, rc=");
Serial.println(client.state());
}
} // end of if (!client.connected())
return client.connected();
} // end of void Reconnect()
// -----------------------------------------------------------------
void DownloadMQTT_detailsFromEEPROM(boolean Print)
{
byte i = 0;
MQTT_Broker = ""; //start with empty string
while (i < MaxStringLength) // build up string from stored characters that are not FF
{
if (EEPROM.read(EEPROM_MQTT_Broker + i) != 255)
MQTT_Broker += char(EEPROM.read(EEPROM_MQTT_Broker + i));
else break;
i++;
}
MQTT_Format = EEPROM.read (EEPROM_MQTT_Format);
MQTT_ServerType = EEPROM.read(EEPROM_MQTT_BrokerType);
i = 0;
user = ""; //start with empty string
while (i < MaxStringLength) // build up string from stored characters that are not FF
{
if (EEPROM.read(EEPROM_MQTT_User + i) != 255)
user += char(EEPROM.read(EEPROM_MQTT_User + i));
else break;
i++;
} // end of while (i < MaxStringLength) // build up string from stored characters that are not FF
i = 0;
MQTT_Pass = ""; //start with empty string
while (i < MaxStringLength) // build up string from stored characters that are not FF
{
if (EEPROM.read(EEPROM_MQTT_Pass + i) != 255)
MQTT_Pass += char(EEPROM.read(EEPROM_MQTT_Pass + i));
else break;
i++;
} // end of while (i < MaxStringLength) // build up string from stored characters that are not FF
if(Print)
{
Serial.print(F("MQTT_Broker Name ")); Serial.println(MQTT_Broker);
Serial.print(F("MQTT_Server Type ")); Serial.println(MQTT_ServerType);
Serial.print(F("MQTT Broker username ")); Serial.println(user);
Serial.print(F("MQTT Broker password ")); Serial.println(MQTT_Pass);
Serial.print("MQTT Format "); Serial.println(MQTT_Format);
}
} // end of void DownloadMQTT_detailsFromEEPROM()
// ----------------------------------------------------------------------
boolean SendRemoteData(byte HouseNode_OLED_ScreenNo,byte Index)
{
boolean Status;
String DataPacket;
if(HouseNode_OLED_ScreenNo > 0) // normally 1 to 4 for remote screens, 0 = send compact data only
{
// ...................... Line 1 ..........................................................
DataPacket = " ";
{
DataPacket = "Mode=O,";
DataPacket += "Screen=E,";
DataPacket += "Text=" + HostName;
byte HouseNode_OLED_LineNo = 1;
Status = SendRemoteDataPacket(DataPacket,HouseNode_OLED_ScreenNo,HouseNode_OLED_LineNo,Index); // send data remotely to screen 1, Line 3
// ............................. Line 2 ....................................
DataPacket = "Mode=H";
HouseNode_OLED_LineNo = 2;
Status = SendRemoteDataPacket(DataPacket,HouseNode_OLED_ScreenNo,HouseNode_OLED_LineNo,Index);
// ....................... Line 3 is blank....................................
// ....................... Line 4 ...........................................
String X = "";
DataPacket = "Text=Pool:";
X = String(AveragePoolTemperature+0.05);
X = X.substring(0,4); //take 3 significant figures
DataPacket += X;
DataPacket += "'C LL:";
DataPacket += String(LightLevel);
DataPacket += "%";
HouseNode_OLED_LineNo = 4;
Status = SendRemoteDataPacket(DataPacket,HouseNode_OLED_ScreenNo, HouseNode_OLED_LineNo,Index); // send data remotely to screen 1, Line 3
// ....................... Line 5 .................................
DataPacket = "Text=Air: ";
X = String(AirTemperature+0.05);
X = X.substring(0,4); //take 3 significant figures
DataPacket += X;
DataPacket += "'C ";
if(BMP280 == 1)
{
X = String(AirPressure+0.5);
X = X.substring(0,4); //take 3 significant figures
DataPacket += X;
DataPacket += "mb";
} // end of if(BMP280 == 1)
else DataPacket = "Text= ";
HouseNode_OLED_LineNo = 5;
Status = SendRemoteDataPacket(DataPacket,HouseNode_OLED_ScreenNo,HouseNode_OLED_LineNo,Index);
// ............................. Line 6 & 7 are blank ....................................
// ............................. Line 8 ..................................................
DataPacket = "Mode=H";
HouseNode_OLED_LineNo = 8;
Status = SendRemoteDataPacket(DataPacket,HouseNode_OLED_ScreenNo,HouseNode_OLED_LineNo,Index);
}
return Status;
} // end of if(HouseNode_OLED_ScreenNo > 0)
else // Screen no = 0 = send compact data format rather than remote screen format
{
DataPacket = "Compact:Pool,";
DataPacket += String(AveragePoolTemperature,1) + ":Air,";
DataPacket += String(AirTemperature,1) + ":Press,";
DataPacket += String(AirPressure,1) + ":LL,";
DataPacket += String(LightLevel);
String Topic;
if(Index == 0) Topic = RecipientHostName;
else if(Index == 1) Topic = RecipientHostName2;
else if(Index == 2) Topic = RecipientHostName3;
else if(Index == 3) Topic = RecipientHostName4;
else Topic = RecipientHostName5;
Topic += "/" + HostName;
if(EnableMessages)
{
Serial.print(F("["));
Serial.print(Topic);
Serial.print("] ");
Serial.println(DataPacket);
}
if(client.publish(Topic.c_str(),DataPacket.c_str()) == true) return true; // true = message sent
else // message failed to send
{
if(EnableMessages) Serial.println(F("Message Failed"));
return false;
}
} // end of else // Screen no = 0 = send compact data format rather than remote screen format
} // void SendRemoteData(HouseNode_OLED_ScreenNo, byte Index)
// --------------------------------------------------------------------------
byte Check_AP_Switch() // returns value depending on how long the AP button is pressed
{
unsigned long Switch_Pressed_Time;
if(digitalRead(AP_Switch) == AP_SwitchOff ) // read & test the button status
{ // if not pressed
Time_Start = millis(); // get time marker in readiness for switch being pressed
return 0;
}
else // switch is ON
{
while (digitalRead(AP_Switch) == AP_SwitchOn) // wait until button is released
{
delay(10);
Switch_Pressed_Time = millis() - Time_Start; // calculate the time since button was pressed(mS)
}
// button released
//if (EnableMessages) Serial.println(Switch_Pressed_Time); // Diagnostic - button duration time (mS)
if(Switch_Pressed_Time >= 1000) return 1; // Wake up Access point
if(Switch_Pressed_Time < 1000) return 0; // button not pressed long enough
} // end of else // switch is ON
} // end of byte Check_AP_Switch()
// ------------------------------------------------------------------------------
void Demon()
{
Serial.print(F("Average Pool Temperature reading = ")); Serial.println(AveragePoolTemperature);
Serial.println("");
Serial.print(F("RemoteDataSend1 ")); Serial.println(RemoteDataSend1);
Serial.print(F("RemoteDataSend2 ")); Serial.println(RemoteDataSend2);
Serial.print(F("RemoteDataSend3 ")); Serial.println(RemoteDataSend3);
Serial.print(F("RemoteDataSend4 ")); Serial.println(RemoteDataSend4);
Serial.print(F("RemoteDataSend5 ")); Serial.println(RemoteDataSend5);
Serial.println("");
Serial.print(F("Light level = "));Serial.println(LightLevel);
Serial.print(F("Setup Access Point is "));
if(AccessPointRunning) Serial.println(F("running")); else Serial.println(F("not running"));
Serial.print(F("Soft Access Point Switch is "));
if(Soft_AP_Switch) Serial.println(F("ON")); else Serial.println(F("OFF"));
Serial.print(F("Serial port diagnostic messaging is "));
if(EnableMessages) Serial.println(F("Enabled")); else Serial.println(F("Disabled"));
Serial.println("");
Display_WiFi_Connection_Status();
} // end of DEMON
// ------------------------------------------------------------------------------
void Check_For_Keyboard_Command() // Used in loop() - checks keyboard for a single character command
{
if (Serial.available() > 0) Command = Serial.read();
{
if (Command == 'd') Demon(); // Download and display all variables
if (Command == 'h' || Command == 'H') Help();
if (Command == 'E') Reset_All_EEPROM();
if (Command == 'm') Toggle_Diagnostic_Messages();
Command = 255;
} // end of if (Serial.available() > 0) Command = Serial.read();
} // end of void Check_For_Keyboard_Command()
// ---------------------------------------------------------------------
void Help() // displays all of the keyboard commands
{
Serial.println(""); Serial.println(Firmware_Version);Serial.println("");
Serial.println(F("AVAILABLE KEYBOARD COMMANDS")); Serial.println("");
Serial.println(F("d = Download and display all of the program variables"));
Serial.println(F("E = Clear all EEPROM to default values (Must reset afterward)"));
Serial.println(F("h = Show this Help menu screen again"));
Serial.println(F("m = Toggle Enable Diagnostic Messsages"));
Serial.println("");
} // end of void Help()
// ---------------------------------------------------------------------
byte Validate_Numerical_Entry_From_Keyboard_Buffer(byte No_Of_Keystrokes, byte Value_Limit) // validate characters in the keyboard buffer and return a value
{
byte Value; // numerical value to be returned from the keyboard buffer. 255 = invalid entry
boolean Invalid_Entry = false;
// test depending on number of keystrokes
if (No_Of_Keystrokes == 1) if(isDigit (KeyboardBuffer[0])) Value = KeyboardBuffer[0] - '0'; else Invalid_Entry = true;
if (No_Of_Keystrokes == 2)
{
if (isDigit(KeyboardBuffer[1]) && isDigit(KeyboardBuffer[0]))
Value = (KeyboardBuffer[1] - '0') + ((KeyboardBuffer[0] - '0') * 10); else Invalid_Entry = true;
} // end of if (No_Of_Keystrokes == 2)
if (No_Of_Keystrokes == 3)
{
if (isDigit(KeyboardBuffer[2]) && isDigit(KeyboardBuffer[1]) && isDigit(KeyboardBuffer[0]))
Value = (KeyboardBuffer[2] - '0') + ((KeyboardBuffer[1] - '0') * 10) + ((KeyboardBuffer[0] - '0') * 100) ;
else Invalid_Entry = true; // if not numeric
} // end of if (No_Of_Keystrokes == 3)
// test for validity - range, null entry, too many characters
if (No_Of_Keystrokes > 3 || No_Of_Keystrokes == 0 || Value > Value_Limit) Invalid_Entry = true;
if (Invalid_Entry)
{
Serial.println(""); Serial.println(F("Invalid Entry")); Serial.println("");
Value = 255;
return Value; // illegal data entry
}
else return Value; // value = numerical keyboard entry or = 255 if not valid
} // end of byte Validate_Numerical_Entry_From_Keyboard_Buffer(byte No_Of_Keystrokes, byte Value_Limit)
// ------------------------------------------------------------------
void Toggle_Diagnostic_Messages() // enable/disable display printout of messages
{
EnableMessages = !EEPROM.read(EEPROM_EnableMessages); // get and invert the current flag status
EEPROM.write(EEPROM_EnableMessages, EnableMessages); // re-write the inverted flag
Serial.print(F("Diag. messages are "));
if (EnableMessages) Serial.println(F("enabled")); else Serial.println(F("disabled"));
EEPROM.commit();
} // end of void Toggle_Diagnostic_Messages()
// ---------------------------------------------------------------------
void Reset_All_EEPROM() // Clear out all of the previous stored configuration entries & reset the device
{ // to default values
unsigned int i = EEPROM_Start_Address; // initial clear out of complete EEPROM block
while(i < 300)
{
EEPROM.write(EEPROM_Start_Address + i , 255);
i++;
}
i = EEPROM_WiFi_SSID;
while(i < EEPROM_WiFi_SSID + MaxStringLength) // stuff default name into SSID
{
EEPROM.write(i, 'S');
i++;
}
i = EEPROM_MQTT_User;
while(i < (EEPROM_MQTT_User + MaxStringLength)) // stuff default name into Password
{
EEPROM.write(i, 'U');
i++;
}
i = EEPROM_MQTT_Pass;
while(i < (EEPROM_MQTT_Pass + MaxStringLength)) // stuff default name into Password
{
EEPROM.write(i, 'P');
i++;
}
i = EEPROM_WiFi_Password;
while(i < (EEPROM_WiFi_Password + MaxStringLength)) // stuff default name into Password
{
EEPROM.write(i, 'P');
i++;
}
i = EEPROM_HostName;
while(i < (EEPROM_HostName + MaxStringLength)) // stuff default name into HostName
{
EEPROM.write(i, 'H');
i++;
}
i = EEPROM_RecipientHostName;
while(i < (EEPROM_RecipientHostName + MaxStringLength))
{
EEPROM.write(i, '1');
i++;
}
i = EEPROM_RecipientHostName2;
while(i < (EEPROM_RecipientHostName2 + MaxStringLength))
{
EEPROM.write(i, '2');
i++;
}
i = EEPROM_RecipientHostName3;
while(i < (EEPROM_RecipientHostName3 + MaxStringLength))
{
EEPROM.write(i, '3');
i++;
}
i = EEPROM_RecipientHostName4;
while(i < (EEPROM_RecipientHostName4 + MaxStringLength))
{
EEPROM.write(i, '4');
i++;
}
i = EEPROM_RecipientHostName5;
while(i < (EEPROM_RecipientHostName5 + MaxStringLength))
{
EEPROM.write(i, '5');
i++;
}
EEPROM.write (EEPROM_EnableMessages,false); // disable disgnostic messages
EEPROM.write (EEPROM_DeepSleepInterval,30);
EEPROM.write (EEPROM_AP_Password,'p'); // AP default password = password
EEPROM.write (EEPROM_AP_Password+1,'a');
EEPROM.write (EEPROM_AP_Password+2,'s');
EEPROM.write (EEPROM_AP_Password+3,'s');
EEPROM.write (EEPROM_AP_Password+4,'w');
EEPROM.write (EEPROM_AP_Password+5,'o');
EEPROM.write (EEPROM_AP_Password+6,'r');
EEPROM.write (EEPROM_AP_Password+7,'d');
EEPROM.write (EEPROM_RemoteDataSend1,false);
EEPROM.write (EEPROM_RemoteDataSend2,false);
EEPROM.write (EEPROM_RemoteDataSend3,false);
EEPROM.write (EEPROM_RemoteDataSend4,false);
EEPROM.write (EEPROM_RemoteDataSend5,false);
EEPROM.write (EEPROM_HouseNode1_OLED_ScreenNo, 1);
EEPROM.write (EEPROM_HouseNode2_OLED_ScreenNo, 1);
EEPROM.write (EEPROM_HouseNode3_OLED_ScreenNo, 1);
EEPROM.write (EEPROM_HouseNode4_OLED_ScreenNo, 1);
EEPROM.write (EEPROM_HouseNode5_OLED_ScreenNo, 1);
EEPROM.write (EEPROM_DarkThreshold,100);
EEPROM.write(EEPROM_PoolTempSensorIndex,1);
EEPROM.write(EEPROM_AirTempSensorIndex,0);
EEPROM.write(EEPROM_BargraphMinimumTemperature,22);
EEPROM.write(EEPROM_MQTT_Format,MQTT_Compact);
EEPROM.write(EEPROM_MQTT_Broker,'M');
EEPROM.write(EEPROM_MQTT_Broker + 1,'Q');
EEPROM.write(EEPROM_MQTT_Broker + 2,'T');
EEPROM.write(EEPROM_MQTT_Broker + 3,'T');
EEPROM.write(EEPROM_MQTT_Broker + 4,'-');
EEPROM.write(EEPROM_MQTT_Broker + 5,'S');
EEPROM.write(EEPROM_MQTT_Broker + 6,'e');
EEPROM.write(EEPROM_MQTT_Broker + 7,'r');
EEPROM.write(EEPROM_MQTT_Broker + 8,'v');
EEPROM.write(EEPROM_MQTT_Broker + 9,'e');
EEPROM.write(EEPROM_MQTT_Broker + 10,'r');
EEPROM.write(EEPROM_MQTT_Broker + 11,255);
EEPROM.write(EEPROM_MQTT_Broker + 12,255);
EEPROM.write(EEPROM_MQTT_Broker + 13,255);
EEPROM.write(EEPROM_MQTT_Broker + 14,255);
EEPROM.write(EEPROM_MQTT_BrokerType, Local);
i=8;
while (i < MaxStringLength)
{
EEPROM.write (EEPROM_AP_Password+i,255);
i++;
}
byte Value; // set up EEPROM header block - indicates that the EEPROM
i = 0; // has been initialised
while (i < 5)
{
EEPROM.write(EEPROM_Header_Block + i, i); // write header byte
i ++;
} // end of while (i < 5)
EEPROM.commit();
Serial.println(F("EEPROM reset to default"));
} // end of void Reset_All_EEPROM()
// ------------------------------------------------------------
void Download_WiFi_Login_Details_From_EEPROM(boolean Display) // Download to memory, the EEPROM stored values of SSID and password
{
unsigned int i = EEPROM_WiFi_SSID;
esid = ""; //start with empty SSID string
while (i < EEPROM_WiFi_SSID + MaxStringLength) // build up SSID string from stored characters that are not FF
{
if (EEPROM.read(i) != 255)
{
esid += char (EEPROM.read(i));
} else break;
i++;
} // end of while (i < EEPROM_WiFi_SSID + MaxStringLength)
i = EEPROM_WiFi_Password;
epass = ""; //start with empty password string
while (i < EEPROM_WiFi_Password + MaxStringLength) // build up password string from stored characters that are not FF
{
if (EEPROM.read(i) != 255)
{
epass += char(EEPROM.read(i));
} else break;
i++;
} // end of while (i < EEPROM_WiFi_Password + MaxStringLength)
i = EEPROM_HostName;
HostName = ""; //start with empty string
while (i < EEPROM_HostName + MaxStringLength) // build up password string from stored characters that are not FF
{
if (EEPROM.read(i) != 255) HostName += char(EEPROM.read(i)); else break;
i++;
} // end of while (i < EEPROM_HostName + MaxStringLength)
i = EEPROM_AP_Password;
passphrase = ""; //start with empty password string
while (i < EEPROM_AP_Password + MaxStringLength) // build up password string from stored characters that are not FF
{
if (EEPROM.read(i) != 255) passphrase += char(EEPROM.read(i)); else break;
i++;
} // end of while (i < EEPROM_AP_Password + MaxStringLength)
i = EEPROM_RecipientHostName;
RecipientHostName = ""; //start with empty string
while (i < EEPROM_RecipientHostName + MaxStringLength) // build up password string from stored characters that are not FF
{
if (EEPROM.read(i) != 255) RecipientHostName += char(EEPROM.read(i)); else break;
i++;
} // end of while (i < EEPROM_RecipientHostName + MaxStringLength)
i = EEPROM_RecipientHostName2;
RecipientHostName2 = ""; //start with empty string
while (i < EEPROM_RecipientHostName2 + MaxStringLength) // build up password string from stored characters that are not FF
{
if (EEPROM.read(i) != 255) RecipientHostName2 += char(EEPROM.read(i)); else break;
i++;
} // end of while (i < EEPROM_RecipientHostName2 + MaxStringLength)
i = EEPROM_RecipientHostName3;
RecipientHostName3 = ""; //start with empty string
while (i < EEPROM_RecipientHostName3 + MaxStringLength) // build up password string from stored characters that are not FF
{
if (EEPROM.read(i) != 255) RecipientHostName3 += char(EEPROM.read(i)); else break;
i++;
} // end of while (i < EEPROM_RecipientHostName3 + MaxStringLength)
i = EEPROM_RecipientHostName4;
RecipientHostName4 = ""; //start with empty string
while (i < EEPROM_RecipientHostName4 + MaxStringLength) // build up password string from stored characters that are not FF
{
if (EEPROM.read(i) != 255) RecipientHostName4 += char(EEPROM.read(i)); else break;
i++;
} // end of while (i < EEPROM_RecipientHostName4 + MaxStringLength)
i = EEPROM_RecipientHostName5;
RecipientHostName5 = ""; //start with empty string
while (i < EEPROM_RecipientHostName5 + MaxStringLength) // build up password string from stored characters that are not FF
{
if (EEPROM.read(i) != 255) RecipientHostName5 += char(EEPROM.read(i)); else break;
i++;
} // end of while (i < EEPROM_RecipientHostName5 + MaxStringLength)
if (Display)
{
Serial.println("");
Serial.print(F("EEPROM SSID: "));
Serial.println(esid); // print final SSID string - diagnostic
Serial.print(F("EEPROM Password: "));
Serial.println(epass); // print final Password string - diagnostic
Serial.print(F("EEPROM HostName: "));
Serial.println(HostName); // print final HostName string - diagnostic
Serial.print(F("EEPROM Access Point Password: "));
Serial.println(passphrase);
Serial.print(F("EEPROM RecipientHostName1: "));
Serial.println(RecipientHostName); // print final HostName string - diagnostic
Serial.print(F("EEPROM RecipientHostName2: "));
Serial.println(RecipientHostName2);
Serial.print(F("EEPROM RecipientHostName3: "));
Serial.println(RecipientHostName3);
Serial.print(F("EEPROM RecipientHostName4: "));
Serial.println(RecipientHostName4);
Serial.print(F("EEPROM RecipientHostName5: "));
Serial.println(RecipientHostName5);
Serial.println("");
}
} // end of void Download_WiFi_Login_Details_From_EEPROM()
// ------------------------------------------------------------
void Display_WiFi_Connection_Status() // display the status of the current WiFi connection
{
Serial.println("");
Serial.print(F("Device name: "));
Serial.println(HostName);
Serial.print(F("SSID: ")); // SSID
Serial.println(WiFi.SSID());
Serial.print(F("Password: "));
Serial.println(epass);
long rssi = WiFi.RSSI(); // print the received signal strength:
Serial.print(F("signal strength (RSSI):"));
Serial.println(rssi);
IPAddress ip = WiFi.localIP();
Serial.print(F("IP Address: ")); // IP address given to the connection
Serial.println(ip);
byte mac[6]; // MAC address
WiFi.macAddress(mac);
Serial.print(F("MAC address: "));
Serial.print(mac[0],HEX);
Serial.print(F(":"));
Serial.print(mac[1],HEX);
Serial.print(F(":"));
Serial.print(mac[2],HEX);
Serial.print(F(":"));
Serial.print(mac[3],HEX);
Serial.print(F(":"));
Serial.print(mac[4],HEX);
Serial.print(F(":"));
Serial.println(mac[5],HEX);
IPAddress subnet = WiFi.subnetMask(); // Subnet mask
Serial.print(F("NetMask: "));
Serial.println(subnet);
IPAddress gateway = WiFi.gatewayIP(); // Gateway address
Serial.print(F("Gateway: "));
Serial.println(gateway);
Serial.println("");
Serial.print(F("Host name of linked HouseNode for remote Tx 1: "));
Serial.println(RecipientHostName);
Serial.print(F("Host name of linked HouseNode for remote Tx 2: "));
Serial.println(RecipientHostName2);
Serial.print(F("Host name of linked HouseNode for remote Tx 3: "));
Serial.println(RecipientHostName3);
Serial.print(F("Host name of linked HouseNode for remote Tx 4: "));
Serial.println(RecipientHostName4);
Serial.print(F("Host name of linked HouseNode for remote Tx 5: "));
Serial.println(RecipientHostName5);
Serial.println("");
} // end of void Display_WiFi_Connection_status
// ---------------------- WIFI --------------------------------------
void WifiConnect() // Connect to the wifi network using the stored credentials
{
WiFi.mode(WIFI_STA); // Set WIFI module to STA mode
byte Login_Wait_Timer = 0; // no of loops waiting for log in success
LoginSuccessfull = true;
if (EnableMessages)
{
Serial.println();
Serial.println(F("Connect to WiFi"));
}
WiFi.persistent(false); // <-- prevents flash wearing?
WiFi.forceSleepWake();
WiFi.begin(esid.c_str(), epass.c_str());
delay(2);
WiFi.hostname(HostName.c_str());
while (WiFi.status() != WL_CONNECTED)
{ // wait for connection whilst flashing the heartbeat LED
Check_For_Keyboard_Command(); // check for any keyboard command
delay(150);
if (EnableMessages) Serial.print(".");
byte i = Check_AP_Switch();
if(i == 1)
{
Soft_AP_Switch = true; // set flag if AP switch pressed for > 1 seconds
LoginSuccessfull = false;
return;
}
delay(150);
Login_Wait_Timer ++;
if ( Login_Wait_Timer >= 90 || Soft_AP_Switch == true) // login attempt fails after 100 loops or aborted by AP switch
{
LoginSuccessfull = false;
break;
} // end of if ( Login_Wait_Timer >= 90 || Soft_AP_Switch == true)
} // end of while (WiFi.status() != WL_CONNECTED)
if(LoginSuccessfull)
{
if (EnableMessages)
{
Serial.println("");
Serial.println(F(" Connected to Network"));
Display_WiFi_Connection_Status();
}
} // end of if(LoginSuccessfull)
else
{
if (EnableMessages)
{
Serial.println();
Serial.println(F("Login failed"));
} // end of if (EnableMessages)
} // end of else
} // end of void WifiConnect()
// ---------------------------------------------------------------------------
void Auto_EEPROM_Check() // test EEPROM Block for correct ID, set EEPROM to default if 1st run
{
byte Value;
byte i = 0;
while (i < 5)
{
Value = EEPROM.read(EEPROM_Header_Block + i);
if (Value != i)
{ // if any one of header block not correct, reset all EEPROM & exit
Serial.println(""); Serial.println(F("EEPROM not initialised"));
Reset_All_EEPROM();
break;
} // end of if (Value != i)
i ++;
} // end of while (i < 5)
} // end of void Auto_EEPROM_Check()
// -------------------------------------------------------------------------------
void GetMeasurements()
{
static float Test_Temp; // simulated mesaurement values for test mode
if(DarkThreshold != 1) // If Mode pin = normal
{
// ----------------- DB18B20 Pool Temperature ----------------------------------
sensors.requestTemperatures(); // Send the command to get temperatures
float TemperatureReading = 0.0;
byte i = 0;
byte NoOfValidMeasurements = 0;
while (i < 30) //Take 50 measurement samples
{
float Temp = sensors.getTempCByIndex(PoolTempSensorIndex);
if ( Temp >= 1.0 && Temp <=70.0) // Validate measurement
{
TemperatureReading += Temp; // add to running total
NoOfValidMeasurements ++; // increment sample counter
}
delay(2);
i++;
}
if(NoOfValidMeasurements > 0) AveragePoolTemperature = TemperatureReading/NoOfValidMeasurements; // calculate average measurement
AirTemperature = sensors.getTempCByIndex(AirTempSensorIndex);
if(EnableMessages)
{
Serial.print(F("PT="));
Serial.print(AveragePoolTemperature,1);
Serial.print(F(" AT="));
Serial.print(AirTemperature,1);
Serial.print(" ");
}
// --------------------- Enclosure Temp & Pressure -----------------------------------------
if(BMP280 == 1) // only if BMP280 fitted
{
HousingTemperature = bmp.readTemperature();
AirPressure = bmp.readPressure()/100.0; // Pa to mb
if(EnableMessages)
{
Serial.print(F("HT="));
Serial.print(HousingTemperature,1);
Serial.print(" P= ");
Serial.println(AirPressure,0);
}
} // end of if(BMP280 == 1) // only if BMP280 fitted
if(EnableMessages) Serial.println("");
} // end of if(DarkThreshold !=1) // If Mode pin = normal
else // Mode pin = test mode
{
Test_Temp ++; // increment Test temperature value
HousingTemperature = 25.0; // test values
AirPressure = 1120.0; // test values
if(Test_Temp < BargraphMinimumTemperature) Test_Temp = BargraphMinimumTemperature; // limit values to LED range
if(Test_Temp > BargraphMinimumTemperature + 7) Test_Temp = BargraphMinimumTemperature; // limit values to LED range
AveragePoolTemperature = Test_Temp; // transfer test value to measurement variable
} // end of else // = test mode
} // end of void GetMeasurements()
// --------------------------------------------------------------------------------
void Bargraph_LEDs() // light up LED row depending on temperature value
{
byte RoundedTemperature = 0;
byte Threshold1 = BargraphMinimumTemperature;
byte Threshold2 = BargraphMinimumTemperature+1;
byte Threshold3 = BargraphMinimumTemperature+2;
byte Threshold4 = BargraphMinimumTemperature+3;
byte Threshold5 = BargraphMinimumTemperature+4;
byte Threshold6 = BargraphMinimumTemperature+5;
byte Threshold7 = BargraphMinimumTemperature+6;
byte Threshold8 = BargraphMinimumTemperature+7;
byte i = 0;
LightLevel = 0;
while(i < 16) //take 16 readings
{
LightLevel += analogRead(0); // read light level - 0-1023
i ++;
}
LightLevel = LightLevel/16; // calculate average value of measurements
LightLevel = (LightLevel*100)/1023; // convert to percentage 0-100%
if(DarkThreshold == 100) RoundedTemperature = byte (AveragePoolTemperature + 0.5) ; // LED's permanently enabled
else // not permantly enabled = auto enable - only when light level is bright
if(LightLevel >= DarkThreshold && DarkThreshold > 0) RoundedTemperature = byte (AveragePoolTemperature + 0.5) ; // daylight detected = enable LED's
// -------------- Evaluate Temperature & switch relevant Bargraph LED ------------------------------------
if(RoundedTemperature < BargraphMinimumTemperature) // if under range of LED's
{
Clear_LEDs(2,7);
DigitalWrite(0, LED_On);
DigitalWrite(1, LED_On);
delay(250);
Clear_LEDs(0,1);
}
else
if(RoundedTemperature == Threshold1)
{
DigitalWrite(0, LED_On);
Clear_LEDs(1,7);
}
else
if(RoundedTemperature == Threshold2)
{
DigitalWrite(0, LED_Off);
DigitalWrite(1, LED_On);
Clear_LEDs(2,7);
}
else
if(RoundedTemperature == Threshold3)
{
DigitalWrite(0, LED_Off);
DigitalWrite(1, LED_Off);
DigitalWrite(2, LED_On);
Clear_LEDs(3,7);
}
else
if(RoundedTemperature == Threshold4)
{
Clear_LEDs(0,2);
DigitalWrite(3, LED_On);
Clear_LEDs(4,7);
}
else
if(RoundedTemperature == Threshold5)
{
Clear_LEDs(0,3);
DigitalWrite(4, LED_On);
Clear_LEDs(5,7);
}
else
if(RoundedTemperature == Threshold6)
{
Clear_LEDs(0,4);
DigitalWrite(5, LED_On);
Clear_LEDs(6,7);
}
else
if(RoundedTemperature == Threshold7)
{
Clear_LEDs(0,5);
DigitalWrite(6, LED_On);
DigitalWrite(7, LED_Off);
}
else
if(RoundedTemperature == Threshold8)
{
Clear_LEDs(0,6);
DigitalWrite(7, LED_On);
}
else
if(RoundedTemperature > Threshold8) // if over range of LED's
{
Clear_LEDs(0,5);
DigitalWrite(6, LED_On);
DigitalWrite(7, LED_On);
delay(250);
Clear_LEDs(6,7);
}
} // end of void Bargraph_LEDs()
// -----------------------------------------------------------------------------------------
void Clear_LEDs(byte Start, byte End) // Start, End = 0 to 7
{
byte LED_Number = Start;
while (LED_Number < End+1)
{
DigitalWrite(LED_Number,LED_Off);
LED_Number ++;
}
} // end of void Clear_LEDs(byte Start, byte End)
// ----------------------------------------------------------------
boolean SendRemoteDataPacket(String DataLine, byte ScreenNo, byte LineNo, byte Index)
// Screen Number = 1 - 10 = screen no on master station OLED
// Index = 0 = linked HouseNode 1, ... 5 = Linked HousNode 5
{ // returns true = send succeeded, false = send failed
if (WiFi.status() == WL_CONNECTED) //Check WiFi connection status
{ // Compose MQTT_Packet using station data
String MQTT_Packet = "";
MQTT_Packet = MQTT_Packet + "Screen" + "," + String(ScreenNo) ;
MQTT_Packet = MQTT_Packet + ":" + "Line" + "," + String(LineNo)+ ":";
MQTT_Packet = MQTT_Packet + "Data" + "," + DataLine;
String Topic;
if(Index == 0) Topic = RecipientHostName;
else if(Index == 1) Topic = RecipientHostName2;
else if(Index == 2) Topic = RecipientHostName3;
else if(Index == 3) Topic = RecipientHostName4;
else Topic = RecipientHostName5;
Topic += "/" + HostName;
if(EnableMessages)
{
Serial.print(F("["));
Serial.print(Topic);
Serial.print("] ");
Serial.println(MQTT_Packet);
}
// ------------- MQTT Push message -------------------
delay(50);
if(client.publish(Topic.c_str(),MQTT_Packet.c_str()) == true) return true; // true = message sent
else // message failed to send
{
if(EnableMessages) Serial.println(F("Message Failed"));
return false;
}
} // end of if (WiFi.status() == WL_CONNECTED) //Check WiFi connection status
else return 1; // Lost Wifi so exit
} // end of boolean SendRemoteDataPacket(String DataLine, byte ScreenNo, byte LineNo, String IP_Add, byte Index)
/* -------------------------------------------------------------------------------------------------------------
boolean RemoteSendEnabled() // returns true if remote transmission of data is enabled
{
if (RemoteDataSend1==true || RemoteDataSend2==true || RemoteDataSend3==true || RemoteDataSend4==true || RemoteDataSend5==true) return true;
else if (MQTT_ServerType == Cloud) return true;
else return false;
} // end of boolean RemoteSendEnabled()
*/
// ---------------------------------------------------------------------------------
void CheckForDeepSleep() // if remote transmission enabled, Deepsleep only required if accesspoint is not runnng & transmission successful
{ // & test leds not enabled
if( AccessPointRunning == false && DarkThreshold != 1)
{
if(MQTT_Format == HAS_Compatible) // if MQTT = HouseNode compatible
{
if (TX_SendSuccessSend1 == Good && TX_SendSuccessSend2 == Good && TX_SendSuccessSend3 == Good
&& TX_SendSuccessSend4 == Good && TX_SendSuccessSend5 == Good) // All data sent successfully
{
if(EnableMessages) Serial.println(F("Long Deep sleep"));
ESP.deepSleep(DeepSleepInterval * 60000000); // set sleep interval
}
else
{
if(EnableMessages) Serial.println(F("Short Deep sleep"));
ESP.deepSleep(20000000); // 20 sec interval for retry
}
} // end of if(MQTT_Format == HAS_Compatible)
else // Single or compact MQTT topics
{
if (TX_SendSuccessSend1 == Good && TX_SendSuccessSend2 == Good && TX_SendSuccessSend3 == Good) // All data sent successfully
{
if(EnableMessages) Serial.println(F("Long Deep sleep"));
ESP.deepSleep(DeepSleepInterval * 60000000); // set sleep interval
}
else
{
if(EnableMessages) Serial.println(F("Short Deep sleep"));
ESP.deepSleep(20000000); // 20 sec interval for retry
}
} // end of else // Single or compact MQTT topics
} // end of if( AccessPointRunning == false && DarkThreshold != 1) == 1)
} // end of void CheckForDeepSleep()
// *****************************************************************************
void Set_Up_Access_Point() // set up & create an access point and web page to allow the login details
// to be changed - will reset the board after the changes have been entered
// Normal login to WiFi network using the stored details
{
WiFi.mode(WIFI_AP_STA);
if (EnableMessages)
{
Serial.println("");
Serial.print(F("Starting up "));
Serial.print(HostName);
Serial.println(F(" Access Point"));
}
// --- LEDs = AP on --------------------------
byte i = 0;
Wire.beginTransmission(Address8574); // Address the PCF8574 chip
Wire.write(Output); // SETUP IO MASK - 1 if INPUT
Wire.endTransmission();
while (i < 8) // set alternative outputs on
{
DigitalWrite(i,LED_Off); // set outputs off
i++;
DigitalWrite(i,LED_On); // set next on
i++;
} // end of while (i < 8) // set alternative outputs on
int n = WiFi.scanNetworks();
st = "";
for (int i = 0; i < n; ++i)
{
// add SSID and RSSI to string st for each network found
st += "
";
st += WiFi.SSID(i);
st += " (";
st += WiFi.RSSI(i);
st += ")";
st += (WiFi.encryptionType(i) == ENC_TYPE_NONE)?" ":"*";
st += "
";
} // end of for (int i = 0; i < n; ++i)
st += "";
// ************* delete these 4 lines if you wish to use default IP address of 192.168.4.1
IPAddress ip(192,168,8,200); // Give Access point a preferred IP Address
IPAddress gateway(192,168,8,200); // Give Access point a preferred gateway address
IPAddress subnet(255,255,255,0); // Give Access point a preferred subnet address
WiFi.softAPConfig(ip,gateway,subnet);
// ***************************************************************************************
ssid = HostName + " - Setup" ; // AP server name is same as the device name
WiFi.softAP(ssid.c_str()); //, passphrase.c_str()); // Create Access Point
serverAP.begin(); // Start the access point webserver
if (EnableMessages)
{
Serial.print("Connect to WiFi Access Point "); Serial.println(ssid);
Serial.print(" & Web page IP address "); Serial.println(WiFi.softAPIP());
Serial.println(F("for Device Setup"));
}
} // end of void Set_Up_Access_Point(void)
// ------------- PCF8574 port expander functions (for LEDs) --------------------------
void PortWrite(byte data) // Write "data" to 8574 port
{
Wire.beginTransmission(Address8574); // Address the PCF8574 chip
Wire.write(data); // send data byte
Wire.endTransmission(); // stop transmitting
} // end of void PortWrite(byte data)
// ---------------------------
byte PortRead()
{
int value;
Wire.requestFrom(Address8574,1);
value = Wire.read();
return value;
} // end of byte PortRead()
// ----------------------------
void DigitalWrite(byte PinNo,boolean Bitstate) // set or reset extended output bit
{
byte Mirror ;
Mirror = PortRead();
bitWrite(Mirror,PinNo,Bitstate);
PortWrite(Mirror);
} // end of void DigitalWrite(byte PinNo,boolean Bitstate)
// -----------------------------
boolean DigitalRead(byte PinNo)
{
byte Mirror ;
boolean Value;
Mirror = PortRead();
Value = bitRead(Mirror,PinNo); // read the addressed bit from the port mirror
return Value;
} // end of boolean DigitalRead(byte PinNo)
// ------------------------------------------------------------------------
void OLED_ScreenSettings() // OLED Auxiliary screen settings
{
String qRemoteTransmission1 = serverAP.arg("RemoteTransmission1");
String qRemoteTransmission2 = serverAP.arg("RemoteTransmission2");
String qRemoteTransmission3 = serverAP.arg("RemoteTransmission3");
String qRemoteTransmission4 = serverAP.arg("RemoteTransmission4");
String qRemoteTransmission5 = serverAP.arg("RemoteTransmission5");
String qRemoteOLEDScreen1 = serverAP.arg("RemoteOLEDScreen1");
String qRemoteOLEDScreen2 = serverAP.arg("RemoteOLEDScreen2");
String qRemoteOLEDScreen3 = serverAP.arg("RemoteOLEDScreen3");
String qRemoteOLEDScreen4 = serverAP.arg("RemoteOLEDScreen4");
String qRemoteOLEDScreen5 = serverAP.arg("RemoteOLEDScreen5");
String qDarkThresholdValue = serverAP.arg("DarkThresholdValue");
String qDeepSleepMinutes = serverAP.arg("DeepSleepMinutes");
String qPoolSensorIndex = serverAP.arg("PoolSensorIndex");
String qrecipientname1 = serverAP.arg("recipientname1");
String qrecipientname2 = serverAP.arg("recipientname2");
String qrecipientname3 = serverAP.arg("recipientname3");
String qrecipientname4 = serverAP.arg("recipientname4");
String qrecipientname5 = serverAP.arg("recipientname5");
String qMQTT_Format = serverAP.arg("MQTT_Format");
boolean EEPROM_Lock = false;
String qBargraphMinimumTemp = serverAP.arg("BargraphMinimumTemp");
if(qMQTT_Format.length() > 0)
{
if(qMQTT_Format == "H" && MQTT_Format != HAS_Compatible)
{
MQTT_Format = HAS_Compatible;
EEPROM.write(EEPROM_MQTT_Format,HAS_Compatible);
EEPROM_Lock = true;
}
else
if(qMQTT_Format == "S" && MQTT_Format != MQTT_Single)
{
MQTT_Format = MQTT_Single;
EEPROM.write(EEPROM_MQTT_Format,MQTT_Single);
EEPROM_Lock = true;
}
else
if(qMQTT_Format == "C" && MQTT_Format != MQTT_Compact)
{
MQTT_Format = MQTT_Compact;
EEPROM.write(EEPROM_MQTT_Format,MQTT_Compact);
EEPROM_Lock = true;
}
} // end of if(qMQTT_Format.length() > 0
if(qBargraphMinimumTemp.length() >0)
{
BargraphMinimumTemperature = qBargraphMinimumTemp.toInt();
EEPROM.write(EEPROM_BargraphMinimumTemperature, BargraphMinimumTemperature);
EEPROM_Lock = true;
}
if(qPoolSensorIndex.length() >0)
{
PoolTempSensorIndex = qPoolSensorIndex.toInt();
EEPROM.write(EEPROM_PoolTempSensorIndex, PoolTempSensorIndex);
if (PoolTempSensorIndex == 0) AirTempSensorIndex = 1;
else AirTempSensorIndex = 0;
EEPROM.write(EEPROM_AirTempSensorIndex, AirTempSensorIndex);
EEPROM_Lock = true;
}
if(qDeepSleepMinutes.length() >0)
{
DeepSleepInterval = qDeepSleepMinutes.toInt();
EEPROM.write(EEPROM_DeepSleepInterval, DeepSleepInterval);
EEPROM_Lock = true;
} // end of if(qDeepSleepMinutes.length() >0)
if(qDarkThresholdValue.length() > 0)
{
DarkThreshold = qDarkThresholdValue.toInt(); // save in working memory
EEPROM.write(EEPROM_DarkThreshold, DarkThreshold); // save in EEPROM
EEPROM_Lock = true;
} // end of if(qDarkThresholdValue.length() > 0)
// -----------------------------------------------------------------
if (MQTT_Format == HAS_Compatible)
{
if(qRemoteTransmission1 == "D" || qRemoteTransmission1 == "E") //a value has been entered into parameter field
{
if(qRemoteTransmission1 == "D") RemoteDataSend1 = false;
else RemoteDataSend1 = true;
EEPROM.write(EEPROM_RemoteDataSend1,RemoteDataSend1);
EEPROM_Lock = true;
}
if(qRemoteTransmission2 == "D" || qRemoteTransmission2 == "E") //a value has been entered into parameter field
{
if(qRemoteTransmission2 == "D") RemoteDataSend2 = false;
else RemoteDataSend2 = true;
EEPROM.write(EEPROM_RemoteDataSend2,RemoteDataSend2);
EEPROM_Lock = true;
}
if(qRemoteTransmission3 == "D" || qRemoteTransmission3 == "E") //a value has been entered into parameter field
{
if(qRemoteTransmission3 == "D") RemoteDataSend3 = false;
else RemoteDataSend3 = true;
EEPROM.write(EEPROM_RemoteDataSend3,RemoteDataSend3);
EEPROM_Lock = true;
}
if(qRemoteTransmission4 == "D" || qRemoteTransmission4 == "E") //a value has been entered into parameter field
{
if(qRemoteTransmission4 == "D") RemoteDataSend4 = false;
else RemoteDataSend4 = true;
EEPROM.write(EEPROM_RemoteDataSend4,RemoteDataSend4);
EEPROM_Lock = true;
}
if(qRemoteTransmission5 == "D" || qRemoteTransmission5 == "E") //a value has been entered into parameter field
{
if(qRemoteTransmission5 == "D") RemoteDataSend5 = false;
else RemoteDataSend5 = true;
EEPROM.write(EEPROM_RemoteDataSend5,RemoteDataSend5);
EEPROM_Lock = true;
}
if(qRemoteOLEDScreen1.length() >0)
{
HouseNode1_OLED_ScreenNo = qRemoteOLEDScreen1.toInt();
EEPROM.write(EEPROM_HouseNode1_OLED_ScreenNo, HouseNode1_OLED_ScreenNo);
EEPROM_Lock = true;
} // end of if(qRemoteOLEDScreen1.length() >0)
if(qRemoteOLEDScreen2.length() >0)
{
HouseNode2_OLED_ScreenNo = qRemoteOLEDScreen2.toInt();
EEPROM.write(EEPROM_HouseNode2_OLED_ScreenNo, HouseNode2_OLED_ScreenNo);
EEPROM_Lock = true;
} // end of if(qRemoteOLEDScreen2.length() >0)
if(qRemoteOLEDScreen3.length() >0)
{
HouseNode3_OLED_ScreenNo = qRemoteOLEDScreen3.toInt();
EEPROM.write(EEPROM_HouseNode3_OLED_ScreenNo, HouseNode3_OLED_ScreenNo);
EEPROM_Lock = true;
} // end of if(qRemoteOLEDScreen3.length() >0)
if(qRemoteOLEDScreen4.length() >0)
{
HouseNode4_OLED_ScreenNo = qRemoteOLEDScreen4.toInt();
EEPROM.write(EEPROM_HouseNode4_OLED_ScreenNo, HouseNode4_OLED_ScreenNo);
EEPROM_Lock = true;
} // end of if(qRemoteOLEDScreen4.length() >0)
if(qRemoteOLEDScreen5.length() >0)
{
HouseNode5_OLED_ScreenNo = qRemoteOLEDScreen5.toInt();
EEPROM.write(EEPROM_HouseNode5_OLED_ScreenNo, HouseNode5_OLED_ScreenNo);
EEPROM_Lock = true;
} // end of if(qRemoteOLEDScreen5.length() >0)
// ................... Process Host name of linked Recipent 1 ...........
if (qrecipientname1.length() > 0) // Only if something has been entered into the Device name web field
{
unsigned int i = EEPROM_RecipientHostName;
while(i < (EEPROM_RecipientHostName + MaxStringLength))
{
EEPROM.write(i, 255); // Clear out all of the previous stored entries for password
i++;
}
i = 0;
while(i < qrecipientname1.length()) // store new device name to EEPROM
{
EEPROM.write(EEPROM_RecipientHostName + i, qrecipientname1[i]);
i++;
}
EEPROM_Lock = true;
} // end of if (qrecipientname1.length() > 0)
// ................... Process Host name of linked Recipient2 ..................................
if (qrecipientname2.length() > 0) // Only if something has been entered into the Device name web field
{
unsigned int i = EEPROM_RecipientHostName2;
while(i < (EEPROM_RecipientHostName2 + MaxStringLength))
{
EEPROM.write(i, 255); // Clear out all of the previous stored entries for password
i++;
}
i = 0;
while(i < qrecipientname2.length()) // store new device name to EEPROM
{
EEPROM.write(EEPROM_RecipientHostName2 + i, qrecipientname2[i]);
i++;
}
EEPROM_Lock = true;
} // end of if (qrecipientname2.length() > 0)
// ................... Process Host name of linked Recipent 3 ......................
if (qrecipientname3.length() > 0) // Only if something has been entered into the Device name web field
{
unsigned int i = EEPROM_RecipientHostName3;
while(i < (EEPROM_RecipientHostName3 + MaxStringLength))
{
EEPROM.write(i, 255); // Clear out all of the previous stored entries for password
i++;
}
i = 0;
while(i < qrecipientname3.length()) // store new device name to EEPROM
{
EEPROM.write(EEPROM_RecipientHostName3 + i, qrecipientname3[i]);
i++;
}
EEPROM_Lock = true;
} // end of if (qrecipientname3.length() > 0)
// ................... Process Host name of linked Recipent 4 ......................
if (qrecipientname4.length() > 0) // Only if something has been entered into the Device name web field
{
unsigned int i = EEPROM_RecipientHostName4;
while(i < (EEPROM_RecipientHostName4 + MaxStringLength))
{
EEPROM.write(i, 255); // Clear out all of the previous stored entries for password
i++;
}
i = 0;
while(i < qrecipientname4.length()) // store new device name to EEPROM
{
EEPROM.write(EEPROM_RecipientHostName4 + i, qrecipientname4[i]);
i++;
}
EEPROM_Lock = true;
} // end of if (qrecipientname4.length() > 0)
// ................... Process Host name of linked Recipent 5 ......................
if (qrecipientname5.length() > 0) // Only if something has been entered into the Device name web field
{
unsigned int i = EEPROM_RecipientHostName5;
while(i < (EEPROM_RecipientHostName5 + MaxStringLength))
{
EEPROM.write(i, 255); // Clear out all of the previous stored entries for password
i++;
}
i = 0;
while(i < qrecipientname5.length()) // store new device name to EEPROM
{
EEPROM.write(EEPROM_RecipientHostName5 + i, qrecipientname5[i]);
i++;
}
EEPROM_Lock = true;
} // end of if (qrecipientname5.length() > 0)
} // end of if (MQTT_Format == HAS_Compatible
if(EEPROM_Lock == true)
{
EEPROM.commit(); // lock in EEPROM
Download_WiFi_Login_Details_From_EEPROM(false);
}
// ---------------------------------------------------------
content = "\r\n";
content += "
Return to the Main Configuration Menu page ";
content += "";
serverAP.send(200, "text/html", content);
//HeartBeat_Tick(); // Feed the HW watchdog!
} // end of void WiFiSetup()
// -----------------------------------------------------------------------
void WiFiConfig() // WiFi Configuration page
{
String qsid = serverAP.arg("ssid"); // check input from web page when submitted
String qpass = serverAP.arg("pass");
String qname = serverAP.arg("name");
String qAPpass = serverAP.arg("APpass");
String qMQTT_BrokerName = serverAP.arg("MQTT_BrokerName");
String qMQTT_BROKER_TYPE = serverAP.arg("MQTT_BROKER_TYPE");
String qMQTT_user = serverAP.arg("MQTT_user");
String qMQTT_pass = serverAP.arg("MQTT_pass");
boolean EEPROM_Lock = false;;
if (qMQTT_user.length() > 0) // Only if something has been entered into the web field
{
user = qMQTT_user;
byte i=0;
while(i < MaxStringLength) // Clear out all of the previous stored entries
{
EEPROM.write(EEPROM_MQTT_User + i, 255);
i++;
}
i=0;
while(i < qMQTT_user.length()) // store new name to EEPROM
{
EEPROM.write(EEPROM_MQTT_User + i, qMQTT_user[i]);
i++;
}
EEPROM_Lock = true;
}
if (qMQTT_pass.length() > 0 && qMQTT_pass != MQTT_Pass) // Only if something has been entered into the web field
{
MQTT_Pass = qMQTT_pass;
byte i=0;
while(i < MaxStringLength) // Clear out all of the previous stored entries
{
EEPROM.write(EEPROM_MQTT_Pass + i, 255);
i++;
}
i=0;
while(i < qMQTT_pass.length()) // store new name to EEPROM
{
EEPROM.write(EEPROM_MQTT_Pass + i, qMQTT_pass[i]);
i++;
}
EEPROM_Lock = true;
}
if (qMQTT_BROKER_TYPE.length() > 0 ) // Only if something has been entered into the web field
{
if(qMQTT_BROKER_TYPE == "C" && MQTT_ServerType == Local)
{
MQTT_ServerType= Cloud;
EEPROM.write(EEPROM_MQTT_BrokerType, Cloud);
EEPROM_Lock = true;
}
else
if(qMQTT_BROKER_TYPE == "L" && MQTT_ServerType == Cloud)
{
MQTT_ServerType = Local;
EEPROM.write(EEPROM_MQTT_BrokerType, Local);
EEPROM_Lock = true;
}
} // end of if (qMQTT_BROKER_TYPE.length() > 0 )
if (qMQTT_BrokerName.length() > 0 ) // Only if something has been entered into the web field
{
byte i=0;
while(i < MaxStringLength) // Clear out all of the previous stored entries
{
EEPROM.write(EEPROM_MQTT_Broker + i, 255);
i++;
}
i=0;
while(i < qMQTT_BrokerName.length()) // store new name to EEPROM
{
EEPROM.write(EEPROM_MQTT_Broker + i, qMQTT_BrokerName[i]);
i++;
}
EEPROM_Lock = true;
} // end of if (qMQTT_BrokerName.length() > 0 )
// .................. Process Network SSID .................................
if (qsid.length() > 0 ) // Only if something has been entered into the SSID web field
{
unsigned int i=EEPROM_WiFi_SSID;
while(i < EEPROM_WiFi_SSID + MaxStringLength) // Clear out all of the previous stored entries for SSID
{
EEPROM.write(i, 255);
i++;
}
i=0;
while(i < qsid.length()) // store new SSID to EEPROM
{
EEPROM.write(EEPROM_WiFi_SSID + i, qsid[i]);
i++;
}
EEPROM_Lock = true;
} // end of if (qsid.length() > 0 ) // Only if something has been entered into the SSID web field
// .................. Process Network password .................................
if (qpass.length() > 0) // Only if something has been entered into the Password web field
{
unsigned int i = EEPROM_WiFi_Password;
while(i < (EEPROM_WiFi_Password + MaxStringLength))
{
EEPROM.write(i, 255); // Clear out all of the previous stored entries for password
i++;
}
i = 0;
while(i < qpass.length()) // store new password to EEPROM
{
EEPROM.write(EEPROM_WiFi_Password + i, qpass[i]);
i++;
}
EEPROM_Lock = true;
} // end of if (qpass.length() > 0) // Only if something has been entered into the Password web field
// ................... Process Device Name ..................................
if (qname.length() > 0) // Only if something has been entered into the Device name web field
{
unsigned int i = EEPROM_HostName;
while(i < (EEPROM_HostName + MaxStringLength))
{
EEPROM.write(i, 255); // Clear out all of the previous stored entries for password
i++;
}
i = 0;
while(i < qname.length()) // store new device name to EEPROM
{
EEPROM.write(EEPROM_HostName + i, qname[i]);
i++;
}
EEPROM_Lock = true;
} // end of if (qname.length() > 0) // Only if something has been entered into the Device name web field
// .................. Process AP password .................................
if (qAPpass.length() > 0) // Only if something has been entered into the Password web field
{
unsigned int i = EEPROM_AP_Password;
while(i < (EEPROM_AP_Password + MaxStringLength))
{
EEPROM.write(i, 255); // Clear out all of the previous stored entries for password
i++;
}
i = 0;
while(i < qAPpass.length()) // store new password to EEPROM
{
EEPROM.write(EEPROM_AP_Password + i, qAPpass[i]);
i++;
}
EEPROM_Lock = true;
} // end of if (qAPpass.length() > 0)
// -----------------------------------------------------------------------------------
if(EEPROM_Lock == true) EEPROM.commit(); // Lock in EEPROM changes
Download_WiFi_Login_Details_From_EEPROM(false);
DownloadMQTT_detailsFromEEPROM(false);
Success_Message(false); // Upload success message to client to AP web page
} // end of void WiFiConfig()
// ------------------------------------------------------------------------------------
void Start()
{
content = " ";
content += "";
content += "
";
serverAP.send(200, "text/html", content);
} // end of void Start()
// -----------------------------------------------------------------------------
byte Get_Decimal_Hours_From_Web_Time_Value(String Time_Value) // Input string = hrs:min(xx:yy) format from Access point web page input.
{ // Returns decimal value. Input must be in the correct format
byte Decimal_Value;
String Hours = String(Time_Value.charAt(0));
Hours += String(Time_Value.charAt(1));
Decimal_Value = Hours.toInt();
return Decimal_Value;
} // end of byte Get_Decimal_Hours_From_Web_Time_Value(String Time_Value)
// ----------------------------------------------------------------------------
byte Get_Decimal_Mins_From_Web_Time_Value(String Time_Value) // Input string = hrs:min(xx:yy) format from Access point web page input.
{ // Returns decimal value. Input must be in the correct format
byte Decimal_Value;
String Minutes = String(Time_Value.charAt(3));
Minutes += String(Time_Value.charAt(4));
Decimal_Value = Minutes.toInt();
return Decimal_Value;
} // end of byte Get_Decimal_Mins_From_Web_Time_Value(String Time_Value)
// ----------------------------------------------------------------------------
byte Convert_From_String_To_Decimal_Number(String String_Number) // Input string number = xxx format from Access point web page input
{ // (max value = 256). Returns decimal value
unsigned int Decimal_Value;
if (String_Number.length() > 3)
{ // String too many characters
Decimal_Value = 0;
}
else
{
Decimal_Value = String_Number.toInt(); // convert string to int (must be numeric string!)
if (Decimal_Value > 255) Decimal_Value = 255;
}
return byte(Decimal_Value);
} // end of byte Convert_From_String_To_Decimal_Number(String String_Number)
// ----------------------------------------------------------------------------
void Success_Message(boolean Reset)
{
// ----------- Display after a sucessful update of any required parameter page-----------------
content = "\r\n";
serverAP.send(200, "text/html", content);
delay(2000);
if(Reset) Reset_Device("From Configuration page");
} // end of void Success_Message(boolean Reset)
// ------------------------------------------------------------
void Reset_Device(String Reason) // Reset the device - method depends on whether HW watchdog is fitted
{
WiFi.softAPdisconnect(true); // precautionary. Ensure that the soft Access point server is disconnected
WiFi.mode(WIFI_STA); // Set WIFI module to STA mode
delay(100);
if (EnableMessages)
{
Serial.print("Forced reset - ");
Serial.println(Reason);
}
ESP.restart();
while(true) delay(10);
} // end of void Reset_Device(String Reason)
// -----------------------------------------------------------