I have a project in which a serial string with running values is sent every second from a controller, that is available to do diagnostics.
This information will then be formatted and displayed as a table on a soft server HTML page.
Using a cell phone, I log onto the local server on the ESP8266, set the IP address of the page, and see the data in the table as the data comes in, with out having to refresh manually. Once I am happy that the system being monitored is fine, I close the web page on my cellphone.
I have been at this for more than a week, doing research and looking for sample code, but have not been successful.
I have written the code on the Arduino IDE, for the serial incoming data, formatted and tested it on the ESP8266.
I verified the data by sending the formatted data out on the serial port and monitored it on a terminal.
I have written the code on the Arduino IDE, to draw up the table, and using local variables, am able to refresh the table with the values by creating a button, and only if I declare a local 'var DataLnx = "string";', and not from a global 'char DataLnx = "string";'.
However when I wish to marry the two sets of codes, using the Arduino IDE, I cannot get the formatted data into the table, and I also cannot get the table to update when the serial data is ready to be displayed in the table.
I know that the serial data is coming in and being formatted correctly, as I can see the serial debugger strings.
Here is the code, minus the Function which formats the data from the serial port string, as that section works.
#include <ESP8266WiFi.h>
#include <ESPAsyncTCP.h>
#include <ESPAsyncWebServer.h>
#define SerCnt 125 // Serial string chars
uint8_t NoComs; // Communications Active
uint8_t Event; // Active event
uint8_t RTime = 0;
const long interval = 4000; // interval at which Serial to update display is a fault(milliseconds)
unsigned long previousMillis = 0; // will store last time Display was updated
unsigned long currentMillis; // Current time
char DisplayData[SerCnt]; // Incomming Serial Data String
char WorkData[SerCnt]; // Working string
uint8_t SerialPos; // Incomming Serial Buffer Pointer
// Display Data Working RAM - Initialize values
char DataLn1[8] = "0.0V" ;
char DataLn2[8] = "0.0A" ;
char DataLn3[8] = "0V" ;
char DataLn4[8] = "0.0A" ;
char DataLn5[8] = "0W" ;
char DataLn6[8] = "0.0A" ;
char DataLn7[14] = "Idle" ;
char DataLn8[9] = "0.0Hz" ;
char DataLn9[8] = "0.0" ;
char DataLn10[8] = "0V" ;
char DataLn11[8] = "0%" ;
char DataLn12[8] = "0\xB0C" ;
char DataLn13[8] = "0S" ;
char DataLn14[8] = "0.0V" ;
char DataLn15[8] = "0.0V" ;
char DataLn16[8] = "0" ;
char DataLn17[8] = "No Coms";
// Web Server Credentials
const char* ssid = "Table Tester";
const char* password = "12345678";
// Create AsyncWebServer object on port 80
AsyncWebServer server(80);
AsyncWebSocket ws("/ws");
// ***********************************************************************
// Server Web Page Format
const char index_html[] PROGMEM = R"rawliteral(
<!DOCTYPE HTML>
<html>
<html lang="en">
<head>
<style>
<title>Aquaduty Display</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
body {background-color: white;}
table, th, td {
border: 1px solid black;
border-collapse: collapse;
}
//Zebra Column generator
thead {
background: #395870;
color: #fff;
}
tbody tr:nth-child(even) {
background: #f0f0f2;
}
</style>
</head>
<body>
<meta name="viewport" content="width=device-width, initial-scale=1">
<table id='myTable' style="width:75%">
<colgroup>
<col span="1" style="width: 40%;">
<col span="1" style="width: 60%;">
</colgroup>
<tr>
<th COLSPAN="2">
<h3>Aquaduty Apricus Display</h3>
</th>
</tr>
<tr>
<th>Description</th>
<th>Value</th>
</tr>
<tr>
<td>PV Volts</td><td style="text-align:right">V</td>
</tr>
<tr>
<td>PV Amps</td>
<td style="text-align:right">A</td>
</tr>
<tr>
<td>Link Volts</td>
<td style="text-align:right">V</td>
</tr>
<tr>
<td>Link Amps</td>
<td style="text-align:right">A</td>
</tr>
<tr>
<td>Motor Power</td>
<td style="text-align:right">W</td>
</tr>
<tr>
<td>Nom Amps </td>
<td style="text-align:right">A</td>
</tr>
<tr>
<td>Status</td>
<td style="text-align:right"></td>
</tr>
<tr>
<td>Frequency</td>
<td style="text-align:right">Hz</td>
</tr>
<tr>
<td>Mot Slope</td>
<td style="text-align:right"></td>
</tr>
<tr>
<td>Link Limit</td>
<td style="text-align:right">V</td>
</tr>
<tr>
<td>Amplitude</td>
<td style="text-align:right">%</td>
</tr>
<tr>
<td>Heatsink Temp</td>
<td style="text-align:right">℃</td>
</tr>
<tr>
<td>Wait Time</td>
<td style="text-align:right">S</td>
</tr>
<tr>
<td>O/C Volts</td>
<td style="text-align:right">V</td>
</tr>
<tr>
<td>MPPT Volts</td>
<td style="text-align:right">V</td>
</tr>
<tr>
<td>Software Ver</td>
<td style="text-align:right"></td>
</tr>
<tr>
<td style="text-align:center">No Coms</td>
<td></td>
</tr>
</table>
<script>
/*
If i place this here then the values in the table do update when i use the
<button onclick="myFunction()">Try it</button> just before the <script> on the web page as a HTML server stand alone test code
// Display Data Working RAM
var DataLn1 = " 56.0V";
var DataLn2 = " 0.0A";
var DataLn3 = " 0V";
var DataLn4 = " 0.0A";
var DataLn5 = " 0W";
var DataLn6 = " 0.0A";
var DataLn7 = " Idle";
var DataLn8 = " 0.0Hz";
var DataLn9 = " 0.0";
var DataLn10 = " 0V";
var DataLn11 = " 0%";
var DataLn12 = " 0\xB0C";
var DataLn13 = " 0S";
var DataLn14 = " 0.0V";
var DataLn15 = " 0.0V";
var DataLn16 = " 0";
var DataLn17 = "No Coms";
*/
// Place new values in the respective table positions when (NoComs == 1)
function myFunction() {
var myTable = document.getElementById('myTable');
myTable.rows[2].cells[1].innerHTML = DataLn1;
myTable.rows[3].cells[1].innerHTML = DataLn2;
myTable.rows[4].cells[1].innerHTML = DataLn3;
myTable.rows[5].cells[1].innerHTML = DataLn4;
myTable.rows[6].cells[1].innerHTML = DataLn5;
myTable.rows[7].cells[1].innerHTML = DataLn6;
myTable.rows[8].cells[1].innerHTML = DataLn7;
myTable.rows[9].cells[1].innerHTML = DataLn8;
myTable.rows[10].cells[1].innerHTML = DataLn9;
myTable.rows[11].cells[1].innerHTML = DataLn10;
myTable.rows[12].cells[1].innerHTML = DataLn11;
myTable.rows[13].cells[1].innerHTML = DataLn12;
myTable.rows[14].cells[1].innerHTML = DataLn13;
myTable.rows[15].cells[1].innerHTML = DataLn14;
myTable.rows[16].cells[1].innerHTML = DataLn15;
myTable.rows[17].cells[1].innerHTML = DataLn16;
myTable.rows[18].cells[0].innerHTML = DataLn17;
}
</script>
</body>
</html>
)rawliteral";
void notFound(AsyncWebServerRequest *request) {
request->send(404, "text/plain", "Not found");
} // notFound()
// ************************************************************************************
void setup() {
Serial.begin(19200); // Open serial port to read
// Clear Registers
RTime = 0;
NoComs = 0;
previousMillis = 0;
SerialPos = 0;
// Set Receive Buffer with ' '
memset(DisplayData, ' ', sizeof(DisplayData-2));
DisplayData[SerCnt-1] = 0;
// Set Up The Timer
previousMillis = millis();
// Start Web Server Credentials
WiFi.softAP(ssid, password);
IPAddress IP = WiFi.softAPIP();
// *****************************************
// Clear Registers
RTime = 0;
NoComs = 0;
previousMillis = 0;
SerialPos = 0;
// Set Receive Buffer with ' '
memset(DisplayData, ' ', sizeof(DisplayData-2));
DisplayData[SerCnt-1] = 0;
// Set Up The Timer
previousMillis = millis();
// *****************************************
server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
request->send_P(200, "text/html", index_html);
}); // server.on
server.begin();
// *****************************************
// Open serial communications and wait for port to open:
Serial.begin(19200); // Open Serial Comms to Tester serial port
} // setup()
void loop() {
// put your main code here, to run repeatedly:
// Read serial input:
if (Serial.available() > 0) // Any bytes in Serial Port
{
char Temp;
Temp = Serial.read();
DisplayData[SerialPos] = Temp;
SerialPos++;
if (Temp == '\r')
{
// Carriage Return - End of Msg
SerialPos = 0; // First position for serial Data
/* This Function not included for discussion
DoSerial(); // Transfer Serial Msg to Display Steings DataLnx
// Returns NoComs True if message succesfully received and formated
*/
if (NoComs == 0) // Clear No Coms Msg
{
Serial.println("StrError"); // Debug Print
// DataLn17 = "No Coms"; // Clear No Coms Message
strcpy(DataLn17,"No Coms");
} // (NoComs == 0)
else
{
Serial.println("StrGood"); // Debug Print
// Print a changing charater (-,/,-,\,*) to alert user that Comms running
if (RTime == 0) // No CHar
{
strcpy(DataLn17,"- ");
} // (RTime == 0)
else if (RTime == 1)
{
strcpy(DataLn17,"/ ");
} // (RTime == 1)
else if (RTime == 2)
{
strcpy(DataLn17,"- ");
} // (RTime == 2)
else if (RTime == 3)
{
strcpy(DataLn17,"\ ");
} // (RTime == 3)
else if (RTime == 4)
{
strcpy(DataLn17,"* ");
} // (RTime == 4)
RTime ++;
if (RTime > 4)
{
RTime = 0;
} // (RTime > 4)
} // else - (NoComs == 0)
currentMillis = millis(); // Read reference Time counts
previousMillis = currentMillis; // Store reference Time Counts
Event = 1; // Run myFunction
// websocket.function = myFunction();
} // (DisplayData[InSerialPtr] == '\r')
else if (SerialPos > SerCnt)
{
Serial.println("StrOver"); // Debug Print
// Clear Serial Receive Buffer
memset(DisplayData, 0, sizeof(DisplayData));
SerialPos = 0; // First position for serial Data
strcpy(DataLn17,"No Coms"); // Clear No Coms Message
currentMillis = millis(); // Read reference Time counts
previousMillis = currentMillis; // Store reference Time Counts
Event = 1; // Run myFunction
// websocket.function = myFunction();
} // else if (InSerialPtr > SerCnt)
} // (Serial.available() > 0)
// -------------------------------------------------
// Time out if no Comms
currentMillis = millis();
if (currentMillis - previousMillis >= interval) // 4 seconds
{
Serial.println("Timeout"); // Debug Print
// save the last time display updated
previousMillis = currentMillis;
NoComs = 0; // No Comms
// Clear Serial Receive Buffer
memset(DisplayData, 0, sizeof(DisplayData));
SerialPos = 0; // First position for serial Data
strcpy(DataLn17,"No Coms"); // Clear No Coms Message
Event = 1; // Run myFunction
// websocket.function = myFunction();
} // (currentMillis - previousMillis >= interval)
} // loop()
I am very new to HTML so there may be some funnies in the above code.
Not sure if a softserver operation or websocket should be used for this application.
Any help to get the HTML myFunction() to use the global char DataLnx= "string" and web page refresh when (Event == 1) would be appreciated.