wol.html 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328
  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  6. <meta http-equiv="X-UA-Compatible" content="ie=edge">
  7. <title>Magic Packet | ESPWoL</title>
  8. <style>
  9. body{
  10. font-family: Arial, sans-serif;
  11. color: #262626;
  12. }
  13. .box {
  14. display: flex;
  15. align-items: center;
  16. justify-content: center;
  17. }
  18. .wallpaper{
  19. position: absolute;
  20. width: 100%;
  21. height: 100%;
  22. left: 0;
  23. top: 0;
  24. background-color: #ffffff;
  25. }
  26. .main{
  27. width: 480px;
  28. height: calc(90vh - 2em);
  29. padding: 1em;
  30. -webkit-box-shadow: 10px 10px 18px 0px rgba(0,0,0,0.14);
  31. -moz-box-shadow: 10px 10px 18px 0px rgba(0,0,0,0.14);
  32. box-shadow: 10px 10px 18px 0px rgba(0,0,0,0.14);
  33. border-radius: 0.6em;
  34. border: 1px solid rgb(172, 172, 172);
  35. position: relative;
  36. background-color: white;
  37. }
  38. .divider{
  39. width: calc(100% - 4em);
  40. padding-top: 0.4em;
  41. margin-bottom: 0.4em;
  42. border-bottom: 1px solid rgb(226, 226, 226);
  43. padding-right: 2em;
  44. padding-left: 2em;
  45. }
  46. small{
  47. color: rgb(59, 59, 59);
  48. }
  49. .codeblock{
  50. padding: 0.6em;
  51. background-color: #242424;
  52. color: white;
  53. }
  54. /* Properties Table */
  55. .table_component {
  56. overflow: auto;
  57. width: 100%;
  58. }
  59. .table_component table {
  60. border: 1px solid #dededf;
  61. height: 100%;
  62. width: 100%;
  63. table-layout: fixed;
  64. border-collapse: collapse;
  65. border-spacing: 1px;
  66. text-align: left;
  67. }
  68. .table_component caption {
  69. caption-side: top;
  70. text-align: left;
  71. }
  72. .table_component th {
  73. border: 1px solid #dededf;
  74. background-color: #eceff1;
  75. color: #000000;
  76. padding: 5px;
  77. }
  78. .table_component td {
  79. border: 1px solid #dededf;
  80. background-color: #ffffff;
  81. color: #000000;
  82. padding: 5px;
  83. }
  84. /* status blinker */
  85. #statusBlinker{
  86. position: absolute;
  87. left: 1em;
  88. bottom: 1em;
  89. width: 1em;
  90. height: 2px;
  91. background-color: rgb(95, 95, 95);
  92. }
  93. #statusBlinker.interval{
  94. background-color: rgb(235, 235, 235);
  95. }
  96. input[type=text] {
  97. width: 100%;
  98. padding: 6px 10px;
  99. margin: 8px 0;
  100. box-sizing: border-box;
  101. }
  102. .themebtn{
  103. padding: 0.6em;
  104. padding-left: 1.2em;
  105. padding-right: 1em;
  106. background-color: #242424;
  107. border-radius: 0.4em;
  108. color: white;
  109. border: none;
  110. cursor: pointer;
  111. }
  112. .themebtn.blue{
  113. background-color: #466bb1;
  114. }
  115. .themebtn.red{
  116. background-color: #b14646;
  117. }
  118. .themebtn:hover{
  119. opacity: 0.6;
  120. }
  121. </style>
  122. </head>
  123. <body>
  124. <div class="wallpaper"></div>
  125. <br>
  126. <div class="box">
  127. <div class="main">
  128. <h2>✨ WoL Magic Packet</h2>
  129. <p>Select a host below to send Wake-on-LAN magic packet for remote startup</p>
  130. <div class="table_component" role="region" tabindex="0">
  131. <table>
  132. <thead>
  133. <tr>
  134. <th>Name</th>
  135. <th>MAC Address</th>
  136. <th>Action</th>
  137. </tr>
  138. </thead>
  139. <tbody id="storedMacList">
  140. <tr>
  141. <td>
  142. </td>
  143. <td>
  144. </td>
  145. <td>
  146. </td>
  147. </tr>
  148. </tbody>
  149. </table>
  150. </div>
  151. <h3>🖥️ Add Computer </h3>
  152. <p>You can add more computer MAC address to the list</p>
  153. <p style="margin-bottom: 0;">Target name: </p>
  154. <input id="nameInput" type="text">
  155. <p style="margin-bottom: 0;">MAC Address: </p>
  156. <input id="macInput" type="text">
  157. <button class="themebtn" onclick="handleAddMacAddress();">Add MAC Address</button>
  158. <br>
  159. <div class="divider"></div>
  160. <small>ESPWoL | Deisnged by tobychui 2023 - 2024</small>
  161. <br><br>
  162. <div><a href="/">Back</a></div>
  163. </div>
  164. </div>
  165. <script>
  166. let currentListOfMacs = [];
  167. function initMacAddressList(){
  168. fetch("/api/mem/read", {
  169. method: "GET",
  170. })
  171. .then(response => {
  172. if (!response.ok) {
  173. throw new Error("Failed to read MAC address list");
  174. }
  175. return response.json();
  176. }).then(data => {
  177. let macTable = document.getElementById("storedMacList");
  178. macTable.innerHTML = "";
  179. currentListOfMacs = data;
  180. if (data.length == 0){
  181. //No devices
  182. macTable.innerHTML = `<tr><td colspan="3">✔️ No stored MAC address</td></tr>`;
  183. }else{
  184. //Create a table
  185. let newTable = "";
  186. for(var i = 0; i < data.length; i++){
  187. newTable += `<tr>
  188. <td>
  189. ${data[i].name}
  190. </td>
  191. <td style="overflow-wrap: break-word; word-break: break-word;">
  192. ${data[i].mac}
  193. </td>
  194. <td>
  195. <button class="themebtn blue" onclick="sendWoL('${data[i].mac}');">Wake</button>
  196. <button class="themebtn red" onclick="delRecord('${data[i].mac}');">Delete</button>
  197. </td>
  198. </tr>`;
  199. }
  200. macTable.innerHTML = newTable;
  201. }
  202. console.log(data);
  203. }).catch(error => {
  204. let macTable = document.getElementById("storedMacList");
  205. macTable.innerHTML = `<tr><td colspan="3">✔️ No stored MAC address</td></tr>`;
  206. console.error("Error:", error);
  207. });
  208. }
  209. initMacAddressList();
  210. function sendWoL(macaddr){
  211. fetch("/api/wol?mac=" + macaddr, {
  212. method: "GET",
  213. })
  214. .then(response => {
  215. if (!response.ok) {
  216. throw new Error("Failed to send WoL packet");
  217. }
  218. //ok! Reset the input fileds
  219. alert("Wake on LAN packet sent!")
  220. return;
  221. })
  222. }
  223. //Remove a record from the list
  224. function delRecord(macaddr){
  225. let newListOfMac = [];
  226. currentListOfMacs.forEach(record => {
  227. if (record.mac != macaddr){
  228. newListOfMac.push(record);
  229. }
  230. });
  231. //save the new list to server
  232. fetch("/api/mem/write?mac=" + JSON.stringify(newListOfMac), {
  233. method: "POST",
  234. headers: {
  235. "Content-Type": "application/json"
  236. },
  237. })
  238. .then(response => {
  239. if (!response.ok) {
  240. throw new Error("Failed to write MAC address list");
  241. }
  242. return;
  243. })
  244. .then(data => {
  245. initMacAddressList();
  246. });
  247. }
  248. function isValidMacAddress(macAddress) {
  249. // MAC address pattern: XX:XX:XX:XX:XX:XX
  250. // Where X is a hexadecimal digit (0-9, A-F)
  251. var macRegex = /^([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})$/;
  252. return macRegex.test(macAddress);
  253. }
  254. function handleAddMacAddress(){
  255. let newName = document.getElementById("nameInput").value;
  256. if (newName.trim() == ""){
  257. alert("Target name is missing!");
  258. return;
  259. }
  260. let newMacAddress = document.getElementById("macInput").value;
  261. newMacAddress = newMacAddress.trim();
  262. if (!isValidMacAddress(newMacAddress)){
  263. alert("Mac address is invalid");
  264. return;
  265. }
  266. //Append the new name and mac to the list
  267. currentListOfMacs.push({
  268. "name":newName,
  269. "mac":newMacAddress
  270. });
  271. fetch("/api/mem/write?mac=" + JSON.stringify(currentListOfMacs), {
  272. method: "POST",
  273. headers: {
  274. "Content-Type": "application/json"
  275. },
  276. })
  277. .then(response => {
  278. if (!response.ok) {
  279. throw new Error("Failed to write MAC address list");
  280. }
  281. //ok! Reset the input fileds
  282. document.getElementById("nameInput").value = "";
  283. document.getElementById("macInput").value = "";
  284. return;
  285. })
  286. .then(data => {
  287. initMacAddressList();
  288. });
  289. }
  290. </script>
  291. </body>
  292. </html>