diff --git a/ESPTimeCast_ESP32/ESPTimeCast_ESP32.ino b/ESPTimeCast_ESP32/ESPTimeCast_ESP32.ino
index 960dd19..43d366e 100644
--- a/ESPTimeCast_ESP32/ESPTimeCast_ESP32.ino
+++ b/ESPTimeCast_ESP32/ESPTimeCast_ESP32.ino
@@ -17,6 +17,8 @@
#include "tz_lookup.h" // Timezone lookup, do not duplicate mapping here!
#include "days_lookup.h" // Languages for the Days of the Week
#include "months_lookup.h" // Languages for the Months of the Year
+#include "index_html.h" // Web UI
+
#define HARDWARE_TYPE MD_MAX72XX::FC16_HW
#define MAX_DEVICES 4
@@ -674,8 +676,8 @@ void printConfigToSerial() {
Serial.println(customMessage);
Serial.print(F("Total Runtime: "));
- if (totalUptimeSeconds > 0) {
- Serial.println(formatUptime(totalUptimeSeconds));
+ if (getTotalRuntimeSeconds() > 0) {
+ Serial.println(formatTotalRuntime());
} else {
Serial.println(F("No runtime recorded yet."));
}
@@ -695,7 +697,7 @@ void setupWebServer() {
server.on("/", HTTP_GET, [](AsyncWebServerRequest *request) {
Serial.println(F("[WEBSERVER] Request: /"));
- request->send(LittleFS, "/index.html", "text/html");
+ request->send_P(200, "text/html", index_html);
});
server.on("/config.json", HTTP_GET, [](AsyncWebServerRequest *request) {
@@ -1883,43 +1885,72 @@ void fetchWeather() {
}
+// -----------------------------
+// Load uptime from LittleFS
+// -----------------------------
void loadUptime() {
if (LittleFS.exists("/uptime.dat")) {
File f = LittleFS.open("/uptime.dat", "r");
if (f) {
totalUptimeSeconds = f.parseInt();
f.close();
+ bootMillis = millis();
Serial.printf("[UPTIME] Loaded accumulated uptime: %lu seconds (%.2f hours)\n",
totalUptimeSeconds, totalUptimeSeconds / 3600.0);
} else {
Serial.println(F("[UPTIME] Failed to open /uptime.dat for reading."));
+ totalUptimeSeconds = 0;
+ bootMillis = millis();
}
} else {
Serial.println(F("[UPTIME] No previous uptime file found. Starting from 0."));
totalUptimeSeconds = 0;
+ bootMillis = millis();
}
}
+// -----------------------------
+// Save uptime to LittleFS
+// -----------------------------
void saveUptime() {
- // Add runtime since boot to total
- unsigned long runtimeSeconds = (millis() - bootMillis) / 1000;
- totalUptimeSeconds += runtimeSeconds;
-
- // Reset bootMillis so next period counts correctly
- bootMillis = millis();
+ // Use getTotalRuntimeSeconds() to include current session
+ totalUptimeSeconds = getTotalRuntimeSeconds();
+ bootMillis = millis(); // reset session start
File f = LittleFS.open("/uptime.dat", "w");
if (f) {
f.print(totalUptimeSeconds);
f.close();
- Serial.printf("[UPTIME] Saved accumulated uptime: %lu seconds (%.2f hours)\n",
- totalUptimeSeconds, totalUptimeSeconds / 3600.0);
+ Serial.printf("[UPTIME] Saved accumulated uptime: %s\n", formatTotalRuntime().c_str());
} else {
Serial.println(F("[UPTIME] Failed to write /uptime.dat"));
}
}
+
+// -----------------------------
+// Get total uptime including current session
+// -----------------------------
+unsigned long getTotalRuntimeSeconds() {
+ return totalUptimeSeconds + (millis() - bootMillis) / 1000;
+}
+
+
+// -----------------------------
+// Format total uptime as HH:MM:SS
+// -----------------------------
+String formatTotalRuntime() {
+ unsigned long secs = getTotalRuntimeSeconds();
+ unsigned int h = secs / 3600;
+ unsigned int m = (secs % 3600) / 60;
+ unsigned int s = secs % 60;
+ char buf[16];
+ sprintf(buf, "%02u:%02u:%02u", h, m, s);
+ return String(buf);
+}
+
+
void saveCustomMessageToConfig(const char *msg) {
Serial.println(F("[CONFIG] Updating customMessage in config.json..."));
@@ -2241,82 +2272,82 @@ void loop() {
}
-// -----------------------------
-// Dimming (auto + manual)
-// -----------------------------
-time_t now_time = time(nullptr);
-struct tm timeinfo;
-localtime_r(&now_time, &timeinfo);
-int curHour = timeinfo.tm_hour;
-int curMinute = timeinfo.tm_min;
-int curTotal = curHour * 60 + curMinute;
+ // -----------------------------
+ // Dimming (auto + manual)
+ // -----------------------------
+ time_t now_time = time(nullptr);
+ struct tm timeinfo;
+ localtime_r(&now_time, &timeinfo);
+ int curHour = timeinfo.tm_hour;
+ int curMinute = timeinfo.tm_min;
+ int curTotal = curHour * 60 + curMinute;
-// -----------------------------
-// Determine dimming start/end
-// -----------------------------
-int startTotal, endTotal;
-bool dimActive = false;
+ // -----------------------------
+ // Determine dimming start/end
+ // -----------------------------
+ int startTotal, endTotal;
+ bool dimActive = false;
-if (autoDimmingEnabled) {
- startTotal = sunsetHour * 60 + sunsetMinute;
- endTotal = sunriseHour * 60 + sunriseMinute;
-} else if (dimmingEnabled) {
- startTotal = dimStartHour * 60 + dimStartMinute;
- endTotal = dimEndHour * 60 + dimEndMinute;
-} else {
- startTotal = endTotal = -1; // not used
-}
-
-// -----------------------------
-// Check if dimming should be active
-// -----------------------------
-if (autoDimmingEnabled || dimmingEnabled) {
- if (startTotal < endTotal) {
- dimActive = (curTotal >= startTotal && curTotal < endTotal);
+ if (autoDimmingEnabled) {
+ startTotal = sunsetHour * 60 + sunsetMinute;
+ endTotal = sunriseHour * 60 + sunriseMinute;
+ } else if (dimmingEnabled) {
+ startTotal = dimStartHour * 60 + dimStartMinute;
+ endTotal = dimEndHour * 60 + dimEndMinute;
} else {
- dimActive = (curTotal >= startTotal || curTotal < endTotal); // overnight
+ startTotal = endTotal = -1; // not used
}
-}
-// -----------------------------
-// Apply brightness / display on-off
-// -----------------------------
-static bool lastDimActive = false; // remembers last state
-int targetBrightness = dimActive ? dimBrightness : brightness;
+ // -----------------------------
+ // Check if dimming should be active
+ // -----------------------------
+ if (autoDimmingEnabled || dimmingEnabled) {
+ if (startTotal < endTotal) {
+ dimActive = (curTotal >= startTotal && curTotal < endTotal);
+ } else {
+ dimActive = (curTotal >= startTotal || curTotal < endTotal); // overnight
+ }
+ }
-// Log only when transitioning
-if (dimActive != lastDimActive) {
- if (dimActive) {
- if (autoDimmingEnabled)
- Serial.printf("[DISPLAY] Automatic dimming setting brightness to %d\n", targetBrightness);
- else if (dimmingEnabled)
- Serial.printf("[DISPLAY] Custom dimming setting brightness to %d\n", targetBrightness);
+ // -----------------------------
+ // Apply brightness / display on-off
+ // -----------------------------
+ static bool lastDimActive = false; // remembers last state
+ int targetBrightness = dimActive ? dimBrightness : brightness;
+
+ // Log only when transitioning
+ if (dimActive != lastDimActive) {
+ if (dimActive) {
+ if (autoDimmingEnabled)
+ Serial.printf("[DISPLAY] Automatic dimming setting brightness to %d\n", targetBrightness);
+ else if (dimmingEnabled)
+ Serial.printf("[DISPLAY] Custom dimming setting brightness to %d\n", targetBrightness);
+ } else {
+ Serial.println(F("[DISPLAY] Waking display (dimming end)"));
+ }
+ lastDimActive = dimActive;
+ }
+
+ // Apply brightness or shutdown
+ if (targetBrightness == -1) {
+ if (!displayOff) {
+ Serial.println(F("[DISPLAY] Turning display OFF (dimming -1)"));
+ P.displayShutdown(true);
+ P.displayClear();
+ displayOff = true;
+ displayOffByDimming = dimActive;
+ displayOffByBrightness = !dimActive;
+ }
} else {
- Serial.println(F("[DISPLAY] Waking display (dimming end)"));
+ if (displayOff && ((dimActive && displayOffByDimming) || (!dimActive && displayOffByBrightness))) {
+ Serial.println(F("[DISPLAY] Waking display (dimming end)"));
+ P.displayShutdown(false);
+ displayOff = false;
+ displayOffByDimming = false;
+ displayOffByBrightness = false;
+ }
+ P.setIntensity(targetBrightness);
}
- lastDimActive = dimActive;
-}
-
-// Apply brightness or shutdown
-if (targetBrightness == -1) {
- if (!displayOff) {
- Serial.println(F("[DISPLAY] Turning display OFF (dimming -1)"));
- P.displayShutdown(true);
- P.displayClear();
- displayOff = true;
- displayOffByDimming = dimActive;
- displayOffByBrightness = !dimActive;
- }
-} else {
- if (displayOff && ((dimActive && displayOffByDimming) || (!dimActive && displayOffByBrightness))) {
- Serial.println(F("[DISPLAY] Waking display (dimming end)"));
- P.displayShutdown(false);
- displayOff = false;
- displayOffByDimming = false;
- displayOffByBrightness = false;
- }
- P.setIntensity(targetBrightness);
-}
// --- IMMEDIATE COUNTDOWN FINISH TRIGGER ---
diff --git a/ESPTimeCast_ESP32/data/config.json b/ESPTimeCast_ESP32/data/config.json
deleted file mode 100644
index 509a440..0000000
--- a/ESPTimeCast_ESP32/data/config.json
+++ /dev/null
@@ -1,34 +0,0 @@
-{
- "ssid": "",
- "password": "",
- "openWeatherApiKey": "",
- "openWeatherCity": "",
- "openWeatherCountry": "",
- "clockDuration": 10000,
- "weatherDuration": 5000,
- "timeZone": "",
- "weatherUnits": "metric",
- "brightness": 10,
- "flipDisplay": false,
- "ntpServer1": "pool.ntp.org",
- "ntpServer2": "time.nist.gov",
- "twelveHourToggle": false,
- "showDayOfWeek": true,
- "showDate": false,
- "showHumidity": false,
- "colonBlinkEnabled": true,
- "language": "en",
- "dimmingEnabled": false,
- "dimStartHour": 18,
- "dimStartMinute": 0,
- "dimEndHour": 8,
- "dimEndMinute": 0,
- "dimBrightness": 2,
- "showWeatherDescription": false,
- "countdown": {
- "enabled": false,
- "targetTimestamp": 0,
- "label": "",
- "isDramaticCountdown": true
- }
-}
\ No newline at end of file
diff --git a/ESPTimeCast_ESP32/data/index.html b/ESPTimeCast_ESP32/index_html.h
similarity index 97%
rename from ESPTimeCast_ESP32/data/index.html
rename to ESPTimeCast_ESP32/index_html.h
index 9cd1a5c..918d608 100644
--- a/ESPTimeCast_ESP32/data/index.html
+++ b/ESPTimeCast_ESP32/index_html.h
@@ -1,1636 +1,1641 @@
-
-
-
-
-
-ESPTimeCast Settings
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
+#pragma once
+// index_html.h
+
+const char index_html[] PROGMEM = R"rawliteral(
+
+
+
+
+
+ESPTimeCast Settings
+
+
+
+
+
+
+
+
+
+
+
+
+)rawliteral";
diff --git a/ESPTimeCast_ESP8266/ESPTimeCast_ESP8266.ino b/ESPTimeCast_ESP8266/ESPTimeCast_ESP8266.ino
index d760c14..d42b5ff 100644
--- a/ESPTimeCast_ESP8266/ESPTimeCast_ESP8266.ino
+++ b/ESPTimeCast_ESP8266/ESPTimeCast_ESP8266.ino
@@ -17,6 +17,8 @@
#include "tz_lookup.h" // Timezone lookup, do not duplicate mapping here!
#include "days_lookup.h" // Languages for the Days of the Week
#include "months_lookup.h" // Languages for the Months of the Year
+#include "index_html.h" // Web UI
+
#define HARDWARE_TYPE MD_MAX72XX::FC16_HW
#define MAX_DEVICES 4
@@ -671,8 +673,8 @@ void printConfigToSerial() {
Serial.println(customMessage);
Serial.print(F("Total Runtime: "));
- if (totalUptimeSeconds > 0) {
- Serial.println(formatUptime(totalUptimeSeconds));
+ if (getTotalRuntimeSeconds() > 0) {
+ Serial.println(formatTotalRuntime());
} else {
Serial.println(F("No runtime recorded yet."));
}
@@ -692,7 +694,7 @@ void setupWebServer() {
server.on("/", HTTP_GET, [](AsyncWebServerRequest *request) {
Serial.println(F("[WEBSERVER] Request: /"));
- request->send(LittleFS, "/index.html", "text/html");
+ request->send_P(200, "text/html", index_html);
});
server.on("/config.json", HTTP_GET, [](AsyncWebServerRequest *request) {
@@ -969,7 +971,6 @@ void setupWebServer() {
});
});
-
server.on("/ap_status", HTTP_GET, [](AsyncWebServerRequest *request) {
Serial.print(F("[WEBSERVER] Request: /ap_status. isAPMode = "));
Serial.println(isAPMode);
@@ -1104,7 +1105,6 @@ void setupWebServer() {
request->send(200, "application/json", "{\"ok\":true}");
});
-
server.on("/set_weatherdesc", HTTP_POST, [](AsyncWebServerRequest *request) {
bool showDesc = false;
if (request->hasParam("value", true)) {
@@ -1644,7 +1644,6 @@ String normalizeWeatherDescription(String str) {
return result;
}
-
bool isNumber(const char *str) {
for (int i = 0; str[i]; i++) {
if (!isdigit(str[i]) && str[i] != '.' && str[i] != '-') return false;
@@ -1661,7 +1660,6 @@ bool isFiveDigitZip(const char *str) {
}
-
// -----------------------------------------------------------------------------
// Weather Fetching and API settings
// -----------------------------------------------------------------------------
@@ -1878,42 +1876,73 @@ void fetchWeather() {
http.end();
}
+
+// -----------------------------
+// Load uptime from LittleFS
+// -----------------------------
void loadUptime() {
if (LittleFS.exists("/uptime.dat")) {
File f = LittleFS.open("/uptime.dat", "r");
if (f) {
totalUptimeSeconds = f.parseInt();
f.close();
+ bootMillis = millis();
Serial.printf("[UPTIME] Loaded accumulated uptime: %lu seconds (%.2f hours)\n",
totalUptimeSeconds, totalUptimeSeconds / 3600.0);
} else {
Serial.println(F("[UPTIME] Failed to open /uptime.dat for reading."));
+ totalUptimeSeconds = 0;
+ bootMillis = millis();
}
} else {
Serial.println(F("[UPTIME] No previous uptime file found. Starting from 0."));
totalUptimeSeconds = 0;
+ bootMillis = millis();
}
}
-void saveUptime() {
- // Add runtime since boot to total
- unsigned long runtimeSeconds = (millis() - bootMillis) / 1000;
- totalUptimeSeconds += runtimeSeconds;
- // Reset bootMillis so next period counts correctly
- bootMillis = millis();
+// -----------------------------
+// Save uptime to LittleFS
+// -----------------------------
+void saveUptime() {
+ // Use getTotalRuntimeSeconds() to include current session
+ totalUptimeSeconds = getTotalRuntimeSeconds();
+ bootMillis = millis(); // reset session start
File f = LittleFS.open("/uptime.dat", "w");
if (f) {
f.print(totalUptimeSeconds);
f.close();
- Serial.printf("[UPTIME] Saved accumulated uptime: %lu seconds (%.2f hours)\n",
- totalUptimeSeconds, totalUptimeSeconds / 3600.0);
+ Serial.printf("[UPTIME] Saved accumulated uptime: %s\n", formatTotalRuntime().c_str());
} else {
Serial.println(F("[UPTIME] Failed to write /uptime.dat"));
}
}
+
+// -----------------------------
+// Get total uptime including current session
+// -----------------------------
+unsigned long getTotalRuntimeSeconds() {
+ return totalUptimeSeconds + (millis() - bootMillis) / 1000;
+}
+
+
+// -----------------------------
+// Format total uptime as HH:MM:SS
+// -----------------------------
+String formatTotalRuntime() {
+ unsigned long secs = getTotalRuntimeSeconds();
+ unsigned int h = secs / 3600;
+ unsigned int m = (secs % 3600) / 60;
+ unsigned int s = secs % 60;
+ char buf[16];
+ sprintf(buf, "%02u:%02u:%02u", h, m, s);
+ return String(buf);
+}
+
+
void saveCustomMessageToConfig(const char *msg) {
Serial.println(F("[CONFIG] Updating customMessage in config.json..."));
@@ -2235,82 +2264,82 @@ void loop() {
}
-// -----------------------------
-// Dimming (auto + manual)
-// -----------------------------
-time_t now_time = time(nullptr);
-struct tm timeinfo;
-localtime_r(&now_time, &timeinfo);
-int curHour = timeinfo.tm_hour;
-int curMinute = timeinfo.tm_min;
-int curTotal = curHour * 60 + curMinute;
+ // -----------------------------
+ // Dimming (auto + manual)
+ // -----------------------------
+ time_t now_time = time(nullptr);
+ struct tm timeinfo;
+ localtime_r(&now_time, &timeinfo);
+ int curHour = timeinfo.tm_hour;
+ int curMinute = timeinfo.tm_min;
+ int curTotal = curHour * 60 + curMinute;
-// -----------------------------
-// Determine dimming start/end
-// -----------------------------
-int startTotal, endTotal;
-bool dimActive = false;
+ // -----------------------------
+ // Determine dimming start/end
+ // -----------------------------
+ int startTotal, endTotal;
+ bool dimActive = false;
-if (autoDimmingEnabled) {
- startTotal = sunsetHour * 60 + sunsetMinute;
- endTotal = sunriseHour * 60 + sunriseMinute;
-} else if (dimmingEnabled) {
- startTotal = dimStartHour * 60 + dimStartMinute;
- endTotal = dimEndHour * 60 + dimEndMinute;
-} else {
- startTotal = endTotal = -1; // not used
-}
-
-// -----------------------------
-// Check if dimming should be active
-// -----------------------------
-if (autoDimmingEnabled || dimmingEnabled) {
- if (startTotal < endTotal) {
- dimActive = (curTotal >= startTotal && curTotal < endTotal);
+ if (autoDimmingEnabled) {
+ startTotal = sunsetHour * 60 + sunsetMinute;
+ endTotal = sunriseHour * 60 + sunriseMinute;
+ } else if (dimmingEnabled) {
+ startTotal = dimStartHour * 60 + dimStartMinute;
+ endTotal = dimEndHour * 60 + dimEndMinute;
} else {
- dimActive = (curTotal >= startTotal || curTotal < endTotal); // overnight
+ startTotal = endTotal = -1; // not used
}
-}
-// -----------------------------
-// Apply brightness / display on-off
-// -----------------------------
-static bool lastDimActive = false; // remembers last state
-int targetBrightness = dimActive ? dimBrightness : brightness;
+ // -----------------------------
+ // Check if dimming should be active
+ // -----------------------------
+ if (autoDimmingEnabled || dimmingEnabled) {
+ if (startTotal < endTotal) {
+ dimActive = (curTotal >= startTotal && curTotal < endTotal);
+ } else {
+ dimActive = (curTotal >= startTotal || curTotal < endTotal); // overnight
+ }
+ }
-// Log only when transitioning
-if (dimActive != lastDimActive) {
- if (dimActive) {
- if (autoDimmingEnabled)
- Serial.printf("[DISPLAY] Automatic dimming setting brightness to %d\n", targetBrightness);
- else if (dimmingEnabled)
- Serial.printf("[DISPLAY] Custom dimming setting brightness to %d\n", targetBrightness);
+ // -----------------------------
+ // Apply brightness / display on-off
+ // -----------------------------
+ static bool lastDimActive = false; // remembers last state
+ int targetBrightness = dimActive ? dimBrightness : brightness;
+
+ // Log only when transitioning
+ if (dimActive != lastDimActive) {
+ if (dimActive) {
+ if (autoDimmingEnabled)
+ Serial.printf("[DISPLAY] Automatic dimming setting brightness to %d\n", targetBrightness);
+ else if (dimmingEnabled)
+ Serial.printf("[DISPLAY] Custom dimming setting brightness to %d\n", targetBrightness);
+ } else {
+ Serial.println(F("[DISPLAY] Waking display (dimming end)"));
+ }
+ lastDimActive = dimActive;
+ }
+
+ // Apply brightness or shutdown
+ if (targetBrightness == -1) {
+ if (!displayOff) {
+ Serial.println(F("[DISPLAY] Turning display OFF (dimming -1)"));
+ P.displayShutdown(true);
+ P.displayClear();
+ displayOff = true;
+ displayOffByDimming = dimActive;
+ displayOffByBrightness = !dimActive;
+ }
} else {
- Serial.println(F("[DISPLAY] Waking display (dimming end)"));
+ if (displayOff && ((dimActive && displayOffByDimming) || (!dimActive && displayOffByBrightness))) {
+ Serial.println(F("[DISPLAY] Waking display (dimming end)"));
+ P.displayShutdown(false);
+ displayOff = false;
+ displayOffByDimming = false;
+ displayOffByBrightness = false;
+ }
+ P.setIntensity(targetBrightness);
}
- lastDimActive = dimActive;
-}
-
-// Apply brightness or shutdown
-if (targetBrightness == -1) {
- if (!displayOff) {
- Serial.println(F("[DISPLAY] Turning display OFF (dimming -1)"));
- P.displayShutdown(true);
- P.displayClear();
- displayOff = true;
- displayOffByDimming = dimActive;
- displayOffByBrightness = !dimActive;
- }
-} else {
- if (displayOff && ((dimActive && displayOffByDimming) || (!dimActive && displayOffByBrightness))) {
- Serial.println(F("[DISPLAY] Waking display (dimming end)"));
- P.displayShutdown(false);
- displayOff = false;
- displayOffByDimming = false;
- displayOffByBrightness = false;
- }
- P.setIntensity(targetBrightness);
-}
// --- IMMEDIATE COUNTDOWN FINISH TRIGGER ---
diff --git a/ESPTimeCast_ESP8266/data/config.json b/ESPTimeCast_ESP8266/data/config.json
deleted file mode 100644
index 509a440..0000000
--- a/ESPTimeCast_ESP8266/data/config.json
+++ /dev/null
@@ -1,34 +0,0 @@
-{
- "ssid": "",
- "password": "",
- "openWeatherApiKey": "",
- "openWeatherCity": "",
- "openWeatherCountry": "",
- "clockDuration": 10000,
- "weatherDuration": 5000,
- "timeZone": "",
- "weatherUnits": "metric",
- "brightness": 10,
- "flipDisplay": false,
- "ntpServer1": "pool.ntp.org",
- "ntpServer2": "time.nist.gov",
- "twelveHourToggle": false,
- "showDayOfWeek": true,
- "showDate": false,
- "showHumidity": false,
- "colonBlinkEnabled": true,
- "language": "en",
- "dimmingEnabled": false,
- "dimStartHour": 18,
- "dimStartMinute": 0,
- "dimEndHour": 8,
- "dimEndMinute": 0,
- "dimBrightness": 2,
- "showWeatherDescription": false,
- "countdown": {
- "enabled": false,
- "targetTimestamp": 0,
- "label": "",
- "isDramaticCountdown": true
- }
-}
\ No newline at end of file
diff --git a/ESPTimeCast_ESP8266/data/index.html b/ESPTimeCast_ESP8266/index_html.h
similarity index 97%
rename from ESPTimeCast_ESP8266/data/index.html
rename to ESPTimeCast_ESP8266/index_html.h
index 9cd1a5c..918d608 100644
--- a/ESPTimeCast_ESP8266/data/index.html
+++ b/ESPTimeCast_ESP8266/index_html.h
@@ -1,1636 +1,1641 @@
-
-
-
-
-
-ESPTimeCast Settings
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
+#pragma once
+// index_html.h
+
+const char index_html[] PROGMEM = R"rawliteral(
+
+
+
+
+
+ESPTimeCast Settings
+
+
+
+
+
+
+
+
+
+
+
+
+)rawliteral";