Skip to content

Commit

Permalink
making global variable live update instead
Browse files Browse the repository at this point in the history
  • Loading branch information
Ammaar-Alam committed Jan 13, 2025
1 parent 6c235cb commit b0e6700
Show file tree
Hide file tree
Showing 3 changed files with 113 additions and 75 deletions.
37 changes: 19 additions & 18 deletions public/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,16 @@ <h2>Door Status</h2>
</label>
<span class="status-text" id="open">OPEN</span>
</div>
<button id="emergencyCloseButton">Emergency Close / Untangle</button>
<div class="manual-buttons-container">
<button id="manualOpenButton" class="manual-btn open-btn">[MANUAL] Open Door</button>
<button id="manualCloseButton" class="manual-btn close-btn">[MANUAL] Close Door</button>
</div>
<p
style="font-size: 12px; font-family: sans-serif; text-align center; color: #848482"
style="font-size: 12px; font-family: sans-serif; text-align: center; color: #848482; margin-top: 20px;"
>
<i
>PS: i know my friends, and to avoid getting kidnapped in the middle of the
night, i enable password authentication when I sleep or when i'm gone for
<i>
PS: i know my friends, and to avoid getting kidnapped in the
middle of the night, i enable password authentication when I sleep or when i'm gone for
days :P
</i>
</p>
Expand All @@ -52,23 +55,21 @@ <h2>Door Status</h2>
<h2>About This Project</h2>
<p>
This is a personal project I worked on over the summer. The switch at the top
really does open or close my door hehe; it sends a command to my proxy server
which routes that command to the Arduino IoT cloud server, relaying that command
to the arduino. That arduino is connected to a motor driver which then spins a
DC motor, reeling a fishing line knotted around my door handle, pulling it down.
really does open or close my door; it sends a command to my proxy server
which routes that command to the Arduino IoT cloud server, and then the Arduino
is connected to a motor driver and DC motor that reels a fishing line around my
door handle.
</p>
<p>
For now, I don't really plan to add any more automation, this project was mainly
inspired by my girlfriend, who joked about wanting to have her own prox for my
room, and (just partly) by my very real problem of locking myself out somewhat
frequently; although it was really fun to learn how to work with arduinos and
circuitry,,, so maybe idk
For now, I don't plan to add more automation. This project was partly
inspired by my girlfriend wanting her own prox for my room, and partly by
my real problem of locking myself out frequently. So, it was fun to learn about
Arduinos and circuitry along the way.
</p>
<p class="disclaimer">
<i>
All the parts I used, including those bought and printed, are all open
source on the Github Repo, including the code, so feel free to make one
yourself :)
All the parts I used, including 3D-printed components and code, are open
source on the Github Repo. Feel free to try making one yourself!
</i>
</p>
<hr />
Expand Down Expand Up @@ -101,4 +102,4 @@ <h2>Connect with Me</h2>
<p>© 2024–25 Ammaar Alam. All rights reserved.</p>
</footer>
</body>
</html>
</html>
113 changes: 65 additions & 48 deletions public/script.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// redirect to HTTPS if accessed over HTTP
// not necessary, but google crawler/url inspect is slow to update cache
if (window.location.protocol !== "https:") {
if (window.location.hostname !== 'localhost' && window.location.hostname !== '127.0.0.1' && window.location.protocol !== "https:") {
window.location.href =
"https://" + window.location.hostname + window.location.pathname + window.location.search;
}
Expand All @@ -25,6 +25,8 @@ document.addEventListener("DOMContentLoaded", function () {
localStorage.setItem("authToken", data.token);
document.querySelector("#login-section").style.display = "none";
document.querySelector(".control-panel").style.display = "block";
// After successful login, fetch the current door status to sync UI.
getDoorStatus();
} else {
document.getElementById("login-error").style.display = "block";
}
Expand All @@ -45,27 +47,58 @@ document.addEventListener("DOMContentLoaded", function () {
// if auth isn't required, hide login and show control panel
document.querySelector("#login-section").style.display = "none";
document.querySelector(".control-panel").style.display = "block";
getDoorStatus();
}
})
.catch((error) => console.error("Error checking auth status:", error));

// fetch door status from server
async function getDoorStatus() {
try {
const headers = { "Content-Type": "application/json" };
if (authRequired) {
const token = localStorage.getItem("authToken");
if (token) {
headers["Authorization"] = token;
}
}
const response = await fetch("/status", {
method: "GET",
headers,
});
if (!response.ok) {
console.error("Failed to get door status:", await response.text());
return;
}
const data = await response.json();
setToggle(data.doorOpen);
} catch (error) {
console.error("Error fetching door status:", error);
}
}

// set toggle state based on doorOpen boolean
function setToggle(isOpen) {
const doorSwitch = document.getElementById("doorSwitch");
doorSwitch.checked = !!isOpen;
updateStatus();
}

async function sendCommand(command) {
try {
const headers = { "Content-Type": "application/json" };
if (authRequired) {
// if auth is required, check for token
const token = localStorage.getItem("authToken");
if (!token) {
console.error("No auth token found. please log in again.");
console.error("No auth token found. Please log in again.");
return;
}
headers["Authorization"] = token;
}

const response = await fetch("/command", {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: authRequired ? localStorage.getItem("authToken") : "", // only add token if auth is required
},
headers,
body: JSON.stringify({ command }),
});

Expand All @@ -74,8 +107,9 @@ document.addEventListener("DOMContentLoaded", function () {
console.error("Failed to send command:", errorDetail);
return;
}

console.log(await response.text());
// Refresh door status after sending command so UI stays in sync
getDoorStatus();
} catch (error) {
console.error("Error during the request:", error);
}
Expand All @@ -86,65 +120,48 @@ document.addEventListener("DOMContentLoaded", function () {
const openStatus = document.getElementById("open");
const closedStatus = document.getElementById("closed");

if (!doorSwitch.checked) {
closedStatus.style.color = "rgba(76, 175, 80, 1)"; // solid green
openStatus.style.color = "#888"; // default gray
} else {
// If switch is checked, door is considered open; otherwise closed
if (doorSwitch.checked) {
openStatus.style.color = "rgba(255, 94, 85, 1)"; // solid red
closedStatus.style.color = "#888"; // default gray
} else {
closedStatus.style.color = "rgba(76, 175, 80, 1)"; // solid green
openStatus.style.color = "#888"; // default gray
}
}

// handle user toggling the switch
function toggleSwitch() {
const doorSwitch = document.getElementById("doorSwitch");
const command = doorSwitch.checked ? "open" : "close";
sendCommand(command);
updateStatus();
}

async function emergencyClose() {
try {
if (authRequired) {
// if auth is required, check for token
const token = localStorage.getItem("authToken");
if (!token) {
console.error("No auth token found. please log in again.");
return;
}
}

const response = await fetch("/emergency-close", {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: authRequired ? localStorage.getItem("authToken") : "", // only add token if auth is required
},
});

if (!response.ok) {
const errorDetail = await response.text();
console.error("Failed to send emergency close command:", errorDetail);
return;
}
// manual open door
function manualOpen() {
sendCommand("open");
}

console.log(await response.text());
} catch (error) {
console.error("Error during emergency close request:", error);
}
// manual close door
function manualClose() {
sendCommand("close");
}

const doorSwitch = document.getElementById("doorSwitch");
if (doorSwitch) {
doorSwitch.onclick = toggleSwitch;
updateStatus(); // initialize the status on page load
doorSwitch.addEventListener("change", toggleSwitch);
} else {
console.error("doorSwitch element not found");
}

const emergencyCloseButton = document.getElementById("emergencyCloseButton");
if (emergencyCloseButton) {
emergencyCloseButton.onclick = emergencyClose;
} else {
console.error("emergencyCloseButton element not found");
// new manual open/close buttons
const openButton = document.getElementById("manualOpenButton");
const closeButton = document.getElementById("manualCloseButton");
if (openButton) {
openButton.onclick = manualOpen;
}
if (closeButton) {
closeButton.onclick = manualClose;
}
});
});
38 changes: 29 additions & 9 deletions public/styles.css
Original file line number Diff line number Diff line change
Expand Up @@ -259,24 +259,44 @@ footer p {
align-items: stretch;
padding: 10px;
}

.social-links a {
justify-content: center;
}
}

#emergencyCloseButton {
background-color: #ff0d00; /* red */
color: #f8f7f9; /* seasalt */
display: none; /* Removed the old emergency close button. */
}

.manual-buttons-container {
display: flex;
align-items: center;
justify-content: center;
margin-top: 20px;
gap: 20px;
}

.manual-btn {
border: none;
border-radius: 5px;
padding: 10px 20px;
font-size: 16px;
padding: 12px 20px;
font-size: 12px;
cursor: pointer;
transition: background-color 0.3s ease;
margin-top: 20px;
margin-bottom: 10px;
color: #f8f7f9; /* seasalt */
background-color: #444; /* fallback */
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.3);
}

.manual-btn:hover {
opacity: 0.9;
}

#emergencyCloseButton:hover {
background-color: #b80900; /* this colour is called "engineering orange" lol seems fitting */
.open-btn {
background-color: #4caf50; /* green */
}

.close-btn {
background-color: #ff5e55; /* red */
}

0 comments on commit b0e6700

Please sign in to comment.