瀏覽代碼

added api

Toby Chui 1 年之前
父節點
當前提交
d86bb7fc85
共有 3 個文件被更改,包括 212 次插入30 次删除
  1. 123 16
      espwol/data/index.html
  2. 2 4
      espwol/espwol.ino
  3. 87 10
      espwol/webserver.ino

+ 123 - 16
espwol/data/index.html

@@ -106,7 +106,7 @@
 		}
 
 		/* Power Button */
-		.pwrbtn {
+		#pwrbtn {
 			display:block;
 			height: 80px;
 			width: 80px;
@@ -117,22 +117,22 @@
 			background-color: #f8f8f8;
 		}
 
-		.pwrbtn:hover{
+		#pwrbtn:hover{
 			background-color: #c7c7c7;
 		}
 
-		.pwrbtn:active{
+		#pwrbtn:active{
 			background-color: #868686;
 			box-shadow: inset 10px 10px 18px 0px rgba(0,0,0,0.38);
 		}
 
-		.pwrbtn svg{
+		#pwrbtn svg{
 			margin-top: 1.5em;
-			margin-left: 0.2em;
+			margin-left: 0.1em;
 		}
 
 		/* Reset Button */
-		.rstbtn {
+		#rstbtn {
 			display:block;
 			height: 40px;
 			width: 40px;
@@ -143,16 +143,16 @@
 			box-shadow: 10px 10px 18px 0px rgba(0,0,0,0.38);
 		}
 
-		.rstbtn svg{
+		#rstbtn svg{
 			margin-top: 0.5em;
-			margin-left: 0.2em;
+			margin-left: 0.1em;
 		}
 
-		.rstbtn:hover{
+		#rstbtn:hover{
 			background-color: #c7c7c7;
 		}
 
-		.rstbtn:active{
+		#rstbtn:active{
 			background-color: #868686;
 			box-shadow: inset 10px 10px 18px 0px rgba(0,0,0,0.38);
 		}
@@ -203,11 +203,11 @@
 						</tr>
 						<tr>
 							<td>Power Status<br></td>
-							<td>OFF</td>
+							<td id="powerLED">OFF</td>
 						</tr>
 						<tr>
 							<td>HDD Status<br></td>
-							<td>IDLE</td>
+							<td id="hddStatus">IDLE</td>
 						</tr>
 					</tbody>
 				</table>
@@ -221,24 +221,131 @@
 			</code></div>
 			<br>
 			<div class="divider"></div>
-			<small>ESPWoL Prototype | CopyRight tobychui 2023 - 2024</small>
+			<small>ESPWoL | Deisnged by tobychui 2023 - 2024</small>
 
 			<div class="controlEmu" align="center">
-				<div class="rstbtn" title="Reset Computer">
+				<div id="rstbtn" title="Reset Computer">
 					<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 -960 960 960" width="24"><path d="M440-122q-121-15-200.5-105.5T160-440q0-66 26-126.5T260-672l57 57q-38 34-57.5 79T240-440q0 88 56 155.5T440-202v80Zm80 0v-80q87-16 143.5-83T720-440q0-100-70-170t-170-70h-3l44 44-56 56-140-140 140-140 56 56-44 44h3q134 0 227 93t93 227q0 121-79.5 211.5T520-122Z"/></svg>
 				</div>
 				<div class="leds">
 					<div class="ledlabel">HDD <div class="led"></div></div><br>
 					<div class="ledlabel">PWR <div class="led"></div></div>
 				 </div>
-				 <div class="pwrbtn" title="Power On / Off">
-					<svg xmlns="http://www.w3.org/2000/svg" height="32" viewBox="0 -960 960 960" width="32"><path d="M440-440v-400h80v400h-80Zm40 320q-74 0-139.5-28.5T226-226q-49-49-77.5-114.5T120-480q0-80 33-151t93-123l56 56q-48 40-75 97t-27 121q0 116 82 198t198 82q117 0 198.5-82T760-480q0-64-26.5-121T658-698l56-56q60 52 93 123t33 151q0 74-28.5 139.5t-77 114.5q-48.5 49-114 77.5T480-120Z"/></svg>
+				 <div id="pwrbtn" title="Power On / Off">
+					<svg id="pwricon" fill="#eb4034" xmlns="http://www.w3.org/2000/svg" height="32" viewBox="0 -960 960 960" width="32"><path d="M440-440v-400h80v400h-80Zm40 320q-74 0-139.5-28.5T226-226q-49-49-77.5-114.5T120-480q0-80 33-151t93-123l56 56q-48 40-75 97t-27 121q0 116 82 198t198 82q117 0 198.5-82T760-480q0-64-26.5-121T658-698l56-56q60 52 93 123t33 151q0 74-28.5 139.5t-77 114.5q-48.5 49-114 77.5T480-120Z"/></svg>
 				 </div>
 			</div>
 		</div>
 	</div>
 	<script>
+		/* 
+			The update interval will change based on the current status of the remote
+			computer. By default, it update the status LED every seconds. When the 
+			remote is powered on, it update with 100ms delay between response and new requests.
+		*/
+		let updateInterval = 1000; 
+		//Set the power status and hdd led status to off
+		togglePowerState(false);
+		toggleHDDLED(false);
 
+		/* Read the status from server */
+		function updateLEDStatus(){
+			fetch('/status', {
+				method: 'GET'
+			})
+			.then(response => {
+				if (!response.ok) {
+					throw new Error('Network error');
+					updateInterval = 1000;
+					setTimeout(updateLEDStatus, updateInterval);
+				}
+				return response.json();
+			})
+			.then(data => {
+				//Update the power LED and update interval
+				togglePowerState(data.pwr);
+				if (data.pwr){
+					updateInterval = 100;
+				}else{
+					updateInterval = 1000;
+				}
+				setTimeout(updateLEDStatus, updateInterval);
+				//Update the hdd led 
+				toggleHDDLED(data.hdd);
+			})
+		}
+		setTimeout(updateLEDStatus, updateInterval);
+
+		/* Status LED Rendering */
+		function togglePowerState(powerIsOn = true){
+			if (powerIsOn){
+				document.getElementById("powerLED").innerHTML = "🟢 ON";
+				document.getElementById("pwricon").setAttribute("fill", "#7fe38b");
+			}else{
+				document.getElementById("powerLED").innerHTML = "⚫ OFF";
+				document.getElementById("pwricon").setAttribute("fill", "#eb4034");
+			}
+		}
+
+		function toggleHDDLED(hddLEDOn = true){
+			if (hddLEDOn){
+				document.getElementById("hddStatus").innerHTML = "🔵 R/W";
+			}else{
+				document.getElementById("hddStatus").innerHTML = "⚫ IDLE";
+			}
+		}
+
+		/* Button Emulations */
+		function handlePowerButtonPress(){
+			fetch('/power/press', {
+				method: 'GET'
+			}).then(response => {
+				if (!response.ok) {
+					console.log("Error when trying to press power button")
+				}
+			});
+		}
+
+		function handlePowerButtonRelease(){
+			fetch('/power/release', {
+				method: 'GET'
+			}).then(response => {
+				if (!response.ok) {
+					console.log("Error when trying to press power button")
+				}
+			});
+		}
+
+		function handleResetButtonPress(){
+			fetch('/reset/press', {
+				method: 'GET'
+			}).then(response => {
+				if (!response.ok) {
+					console.log("Error when trying to press reset button")
+				}
+			});
+		}
+
+		function handlResetButtonRelease(){
+			fetch('/reset/release', {
+				method: 'GET'
+			}).then(response => {
+				if (!response.ok) {
+					console.log("Error when trying to press reset button")
+				}
+			});
+		}
+
+		/* Bind events for the buttons */
+		document.getElementById("pwrbtn").addEventListener("mousedown", handlePowerButtonPress);
+		document.getElementById("pwrbtn").addEventListener("touchstart", handlePowerButtonPress);
+		document.getElementById("pwrbtn").addEventListener("mouseup", handlePowerButtonRelease);
+		document.getElementById("pwrbtn").addEventListener("touchend", handlePowerButtonRelease);
+
+		document.getElementById("rstbtn").addEventListener("mousedown", handleResetButtonPress);
+		document.getElementById("rstbtn").addEventListener("touchstart", handleResetButtonPress);
+		document.getElementById("rstbtn").addEventListener("mouseup", handlResetButtonRelease);
+		document.getElementById("rstbtn").addEventListener("touchend", handlResetButtonRelease);
 	</script>
 </body>
 </html>

+ 2 - 4
espwol/espwol.ino

@@ -34,7 +34,7 @@ ESP8266WebServer server(80);
 
 /* Discovery */
 #include <ESP8266mDNS.h>
-String MDNS_NAME = "espwol";
+String MDNS_NAME = "espwol" + WiFi.macAddress();
 
 /* Global Variables */
 bool hddLedState = 0;
@@ -89,7 +89,5 @@ void setup() {
 void loop() {
   server.handleClient();
   handleCustomButtonEvents();
-  Serial.print(hddLedState);
-  Serial.print(",");
-  Serial.println(pwrLedState);
+  updateFrontPanelLEDStatus();
 }

+ 87 - 10
espwol/webserver.ino

@@ -1,20 +1,97 @@
 /*
- * 
- *  Webserver.ino
- *  
- *  This script handle web serving and RESTFUL API features
- */
-
-void registerServeEndpoints(){
-  server.serveStatic("/", LittleFS, "/index.html"); 
+
+    Webserver.ino
+
+    This script handle web serving and RESTFUL API features
+*/
+
+void registerServeEndpoints() {
+  server.serveStatic("/", LittleFS, "/index.html");
+
+  /* Button Actions */
+  server.on("/power/press", handlePowerBtnPress);
+  server.on("/power/release", handlePowerBtnRelease);
+  server.on("/reset/press", handleResetBtnPress);
+  server.on("/reset/release", handleResetBtnRelease);
+  server.on("/status", handleStatus);
+  
+  /* RESTFUL API */
+  server.on("/api/status", handleStatus);
+  server.on("/api/power", handlePowerSequence);
+  server.on("/api/reset", handleResetSequence);
+
   server.onNotFound(handleNotFound);
 }
 
-void handleRoot() {
-  //server.send(200, "text/plain", "Hello world!"); 
+void sendOK(){
+  server.send(200, "application/json", "\"ok\"");
+}
+
+/* Emulate the power button press events in hardware */
+void handlePowerBtnPress() {
+  digitalWrite(PWR_BTN, HIGH);
+  digitalWrite(BTN_LED, LOW);
+  Serial.println("[INFO] Power button pressed");
+  sendOK();
+}
+
+void handlePowerBtnRelease() {
+  digitalWrite(PWR_BTN, LOW);
+  digitalWrite(BTN_LED, HIGH);
+  Serial.println("[INFO] Power button released");
+  sendOK();
+}
+
+/* Emulate the reset button press events in hardware */
+void handleResetBtnPress() {
+  digitalWrite(RST_BTN, HIGH);
+  digitalWrite(BTN_LED, LOW);
+  Serial.println("[INFO] Reset button pressed");
+  sendOK();
 }
 
+void handleResetBtnRelease() {
+  digitalWrite(RST_BTN, LOW);
+  digitalWrite(BTN_LED, HIGH);
+  Serial.println("[INFO] Reset button released");
+  sendOK();
+}
+
+
+//Serving the LED status 
+void handleStatus(){
+  //Create a JSON object, 64 should be more than enough bytes to work with
+  StaticJsonDocument<64> jsonDoc;
+  jsonDoc["hdd"] = hddLedState;
+  jsonDoc["pwr"] = pwrLedState;
+  String jsonString;
+  serializeJson(jsonDoc, jsonString);
+  server.send(200, "application/json", jsonString);
+}
+
+//Handle power up sequence
+void handlePowerSequence() {
+  if (server.method() == HTTP_POST) {
+    Serial.println("[INFO] Toggling power button via RESTFUL API");
+    pressPowerButton();
+    sendOK();
+  } else {
+    server.send(405, "text/plain", "Method Not Allowed");
+  }
+}
+
+//Handle reset sequence
+void handleResetSequence() {
+  if (server.method() == HTTP_POST) {
+    Serial.println("[INFO]  Toggling reset button via RESTFUL API");
+    pressResetButton();
+    sendOK();
+  } else {
+    server.send(405, "text/plain", "Method Not Allowed");
+  }
+}
 
+// Default not found handler
 void handleNotFound() {
   String message = "404 - Not Found\n\n";
   message += "URI: ";