123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351 |
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <meta http-equiv="X-UA-Compatible" content="ie=edge">
- <title>ESPWoL</title>
- <style>
- body{
- font-family: Arial, sans-serif;
- color: #262626;
- }
- .box {
- display: flex;
- align-items: center;
- justify-content: center;
- }
- .wallpaper{
- position: absolute;
- width: 100%;
- height: 100%;
- left: 0;
- top: 0;
- background-color: #ffffff;
- }
-
- .main{
- width: 480px;
- height: calc(90vh - 2em);
- padding: 1em;
- -webkit-box-shadow: 10px 10px 18px 0px rgba(0,0,0,0.14);
- -moz-box-shadow: 10px 10px 18px 0px rgba(0,0,0,0.14);
- box-shadow: 10px 10px 18px 0px rgba(0,0,0,0.14);
- border-radius: 0.6em;
- border: 1px solid rgb(172, 172, 172);
- position: relative;
- background-color: white;
- }
- .divider{
- width: calc(100% - 4em);
- padding-top: 0.4em;
- margin-bottom: 0.4em;
- border-bottom: 1px solid rgb(226, 226, 226);
- padding-right: 2em;
- padding-left: 2em;
- }
- small{
- color: rgb(59, 59, 59);
- }
- .codeblock{
- padding: 0.6em;
- background-color: #242424;
- color: white;
- }
- /* Properties Table */
- .table_component {
- overflow: auto;
- width: 100%;
- }
- .table_component table {
- border: 1px solid #dededf;
- height: 100%;
- width: 100%;
- table-layout: fixed;
- border-collapse: collapse;
- border-spacing: 1px;
- text-align: left;
- }
- .table_component caption {
- caption-side: top;
- text-align: left;
- }
- .table_component th {
- border: 1px solid #dededf;
- background-color: #eceff1;
- color: #000000;
- padding: 5px;
- }
- .table_component td {
- border: 1px solid #dededf;
- background-color: #ffffff;
- color: #000000;
- padding: 5px;
- }
- /* Front Panel UI emulation */
- .controlEmu{
- position: absolute;
- right: 1.2em;
- bottom: 1.2em;
- padding: 1em;
- border-radius: 0.6em;
- background-color: #ececec;
- border: 1px solid rgb(197, 197, 197);
- }
- /* Power Button */
- #pwrbtn {
- display:block;
- height: 80px;
- width: 80px;
- border-radius: 50%;
- border: 1px solid rgba(156, 156, 156, 0.5);
- cursor: pointer;
- box-shadow: 10px 10px 18px 0px rgba(0,0,0,0.38);
- background-color: #f8f8f8;
- }
- #pwrbtn:hover{
- background-color: #c7c7c7;
- }
- #pwrbtn:active{
- background-color: #868686;
- box-shadow: inset 10px 10px 18px 0px rgba(0,0,0,0.38);
- }
- #pwrbtn svg{
- margin-top: 1.5em;
- margin-left: 0.1em;
- }
- /* Reset Button */
- #rstbtn {
- display:block;
- height: 40px;
- width: 40px;
- border-radius: 50%;
- border: 1px solid rgba(156, 156, 156, 0.5);
- cursor: pointer;
- margin-bottom: 1em;
- box-shadow: 10px 10px 18px 0px rgba(0,0,0,0.38);
- }
- #rstbtn svg{
- margin-top: 0.5em;
- margin-left: 0.1em;
- }
- #rstbtn:hover{
- background-color: #c7c7c7;
- }
- #rstbtn:active{
- background-color: #868686;
- box-shadow: inset 10px 10px 18px 0px rgba(0,0,0,0.38);
- }
- /* LEDs */
- .leds{
- margin-bottom: 1em;
- }
- .ledlabel{
- color: rgb(83, 83, 83);
- font-size: 0.8em;
- pointer-events: none;
- user-select: none;
- }
- .led {
- display:block;
- height: 10px;
- width: 10px;
- border-radius: 50%;
- background-color: #242424;
- }
- </style>
- </head>
- <body>
- <div class="wallpaper"></div>
- <br>
- <div class="box">
- <div class="main">
- <h2>🔌 ESPWoL Control Panel</h2>
- <p>Press a button on the bottom to power up / shutdown / reset your computer wirelessly</p>
- <div class="table_component" role="region" tabindex="0">
- <table>
- <thead>
- <tr>
- <th>Properties</th>
- <th>Status</th>
- </tr>
- </thead>
- <tbody>
- <tr>
- <td>
- <div>WLAN IP<br></div>
- </td>
- <td>0.0.0.0</td>
- </tr>
- <tr>
- <td>Power Status<br></td>
- <td id="powerLED">OFF</td>
- </tr>
- <tr>
- <td>HDD Status<br></td>
- <td id="hddStatus">IDLE</td>
- </tr>
- </tbody>
- </table>
- </div>
- <h3>🤖 RESTFUL API </h3>
- <p>You can also access the power status and controls via RESTFUL API requests.</p>
- <div class="codeblock"><code>
- GET /api/status <br>
- POST /api/power <br>
- POST /api/reset <br>
- </code></div>
- <br>
- <div class="divider"></div>
- <small>ESPWoL | Deisnged by tobychui 2023 - 2024</small>
- <div class="controlEmu" align="center">
- <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 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>
|