Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Fix] Laundry Rewrite to Account For New SpeedQueen API #308

Draft
wants to merge 2 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
125 changes: 56 additions & 69 deletions backend/laundry/api_wrapper.py
Original file line number Diff line number Diff line change
@@ -1,46 +1,50 @@
import requests
from bs4 import BeautifulSoup
from django.conf import settings
from django.utils import timezone
from requests.exceptions import ConnectTimeout, HTTPError, ReadTimeout
from requests.exceptions import HTTPError

from laundry.models import LaundryRoom, LaundrySnapshot


HALL_URL = f"{settings.LAUNDRY_URL}/?location="
def get_room_url(room_id: int):
return f"{settings.LAUNDRY_URL}/rooms/{room_id}/machines?raw=true"


def update_machine_object(cols, machine_object):
def update_machine_object(machine, machine_type_data):
"""
Updates Machine status and time remaining
"""

if cols[2].getText() in ["In use", "Almost done"]:
time_remaining = cols[3].getText().split(" ")[0]
machine_object["running"] += 1
# TODO: Early stage in update 9/29/2024, known status codes are
# TODO: "IN_USE", "AVAILABLE", "COMPLETE";
# TODO: need to update if we identify other codes, especially error
status = machine["currentStatus"]["statusId"]
if status == "IN_USE":
time_remaining = machine[3].getText().split(" ")[0]
machine_type_data["running"] += 1
try:
machine_object["time_remaining"].append(int(time_remaining))
machine_type_data["time_remaining"].append(int(time_remaining))
except ValueError:
pass
elif cols[2].getText() == "Out of order":
machine_object["out_of_order"] += 1
elif cols[2].getText() == "Not online":
machine_object["offline"] += 1
elif status in ["AVAILABLE", "COMPLETE"]:
machine_type_data["open"] += 1
# TODO: Verify there are no other statuses
else:
machine_object["open"] += 1
machine_type_data["offline"] += 1

# edge case that handles machine not sending time data
diff = int(machine_object["running"]) - len(machine_object["time_remaining"])
# TODO: I don't think we need this?
diff = int(machine_type_data["running"]) - len(machine_type_data["time_remaining"])
while diff > 0:
machine_object["time_remaining"].append(-1)
machine_type_data["time_remaining"].append(-1)
diff = diff - 1

return machine_object
return machine_type_data


def parse_a_hall(hall_link):
def parse_a_room(room_request_link):
"""
Return names, hall numbers, and the washers/dryers available for a certain hall_id
Return names, hall numbers, and the washers/dryers available for a certain room_id
"""

washers = {"open": 0, "running": 0, "out_of_order": 0, "offline": 0, "time_remaining": []}
Expand All @@ -49,40 +53,33 @@ def parse_a_hall(hall_link):
detailed = []

try:
page = requests.get(
hall_link,
timeout=60,
headers={"Authorization": "Basic Sure-Nothing-Could-Go-Wrong-With-This-HaHa-Not"},
)
# page = requests.get(hall_link, timeout=60)
except (ConnectTimeout, ReadTimeout):
request = requests.get(room_request_link, timeout=60, headers=settings.LAUNDRY_HEADERS)
request.raise_for_status()
except HTTPError:
return {"washers": washers, "dryers": dryers, "details": detailed}

soup = BeautifulSoup(page.content, "html.parser")
soup.prettify()

rows = soup.find_all("tr")
for row in rows:
cols = row.find_all("td")
if len(cols) > 1:
machine_type = cols[1].getText()
if machine_type == "Washer":
washers = update_machine_object(cols, washers)
elif machine_type == "Dryer":
dryers = update_machine_object(cols, dryers)
if machine_type in ["Washer", "Dryer"]:
try:
time = int(cols[3].getText().split(" ")[0])
except ValueError:
time = 0
detailed.append(
{
"id": int(cols[0].getText().split(" ")[1][1:]),
"type": cols[1].getText().lower(),
"status": cols[2].getText(),
"time_remaining": time,
}
)
request_json = request.json()

[
update_machine_object(machine, washers) if machine["isWasher"] else None
for machine in request_json
]
[
update_machine_object(machine, dryers) if machine["isDryer"] else None
for machine in request_json
]
[
detailed.append(
{
"id": machine["id"],
"type": "washer" if machine["isWasher"] else "dryer",
"status": machine["currentStatus"]["statusId"],
"time_remaining": machine["currentStatus"]["remainingSeconds"],
}
)
for machine in request_json
if machine["isWasher"] or machine["isDryer"]
]

return {"washers": washers, "dryers": dryers, "details": detailed}
dr-Jess marked this conversation as resolved.
Show resolved Hide resolved

Expand All @@ -93,25 +90,16 @@ def check_is_working():
"""

try:
r = requests.post(
"{}/".format(settings.LAUNDRY_URL),
all_rooms_request = requests.get(
f"{settings.LAUNDRY_URL}/geoBoundaries/5610?raw=true",
timeout=60,
headers={"Authorization": "Basic Sure-Nothing-Could-Go-Wrong-With-This-HaHa-Not"},
data={
"locationid": "5faec7e9-a4aa-47c2-a514-950c03fac460",
"email": "[email protected]",
"washers": 0,
"dryers": 0,
"locationalert": "OK",
},
)
r.raise_for_status()
return (
"The transaction log for database 'QuantumCoin' is full due to 'LOG_BACKUP'."
not in r.text
headers=settings.LAUNDRY_HEADERS,
)
all_rooms_request.raise_for_status()

except HTTPError:
return False
return True


def all_status():
Expand All @@ -120,16 +108,16 @@ def all_status():
"""

return {
room.name: parse_a_hall(HALL_URL + str(room.uuid)) for room in LaundryRoom.objects.all()
room.name: parse_a_room(get_room_url(room.room_id)) for room in LaundryRoom.objects.all()
}


def hall_status(room):
def room_status(room):
"""
Return the status of each specific washer/dryer in a particular hall_id
"""

machines = parse_a_hall(HALL_URL + str(room.uuid))
machines = parse_a_room(get_room_url(room.room_id))

return {"machines": machines, "hall_name": room.name, "location": room.location}

Expand All @@ -145,7 +133,6 @@ def save_data():
data = all_status()

for name, room in data.items():

laundry_room = LaundryRoom.objects.get(name=name)

LaundrySnapshot.objects.create(
Expand Down
106 changes: 53 additions & 53 deletions backend/laundry/data/laundry_data.csv
Original file line number Diff line number Diff line change
@@ -1,53 +1,53 @@
0,Bishop White,Quad,5faec7e9-a4aa-47c2-a514-950c03fac460,9,9
1,Chestnut Butcher,Quad,7dfa4b34-f44a-4a38-a6b9-44cdb968a915,11,11
2,Class of 1928 Fisher,Quad,e6697dca-d164-4980-8843-ea0a29b1cf49,8,8
3,Craig,Quad,37d661ce-3e50-4746-ab68-a5c61cd0bd0a,3,3
4,DuBois,DuBois,3ffa8978-e742-4076-9bcb-4a3e5c0eca92,6,6
5,English House,KCEH,b655a5be-1287-4ce2-b693-e9c1ae526f38,3,3
6,Harnwell Floor 02,Harnwell,1c7a9fb3-a938-4756-83c6-42d601d46036,3,3
7,Harnwell Floor 04,Harnwell,fba67cc0-336e-42f7-9603-c0b8a0e5030c,3,3
8,Harnwell Floor 06,Harnwell,87195ec7-eb3d-42fd-84aa-d63f4e45e285,3,3
9,Harnwell Floor 08,Harnwell,1bbb2ff6-d5e6-406d-a3a2-96c7972cceeb,3,3
10,Harnwell Floor 10,Harnwell,987bf30b-e8e1-4a9e-b842-c9cd8aeafddc,3,3
11,Harnwell Floor 12,Harnwell,dcb76f10-0137-4783-8604-bece4111b6dd,3,3
12,Harnwell Floor 14,Harnwell,941b2fcb-2b1b-4afd-8e8e-c100fbcbe0f2,3,3
13,Harnwell Floor 16,Harnwell,c74b2798-2d09-42a6-b65c-a5834219be59,3,3
14,Harnwell Floor 18,Harnwell,f30af904-72ad-49f6-aecf-f44c8301fb6b,3,3
15,Harnwell Floor 20,Harnwell,80a413fd-e0fa-456d-b922-f1576ded1f98,3,3
16,Harnwell Floor 22,Harnwell,35119e5e-92c0-45fb-bfeb-f2059196f644,3,3
17,Harnwell Floor 24,Harnwell,5880b051-8216-4cf4-92d6-5c7475f43eea,3,3
18,Harrison Floor 04,Harrison,447b5682-4c3c-441d-ab49-5f45aee6991f,3,3
19,Harrison Floor 06,Harrison,f77f7c68-f719-4843-8987-d64dabc0abff,3,3
20,Harrison Floor 08,Harrison,6561bb14-634f-437d-84fd-a0837ef991e7,3,3
21,Harrison Floor 10,Harrison,2dd7a63d-7d13-48e5-b038-98054b4f039f,3,3
22,Harrison Floor 12,Harrison,fdb607c7-63eb-4d55-a312-0c16b682cbe7,3,3
23,Harrison Floor 14,Harrison,53fdd440-e887-49e1-9ca9-7bb3cb4ab541,3,3
24,Harrison Floor 16,Harrison,8cedf60a-8f87-4128-89dd-4c75343ca64a,3,3
25,Harrison Floor 18,Harrison,116a8d6f-045b-47a5-b3f7-af31f4e661eb,3,3
26,Harrison Floor 20,Harrison,f6a8b303-1302-49e6-be53-c8e345316ed8,3,3
27,Harrison Floor 22,Harrison,b21c78af-1ebf-418c-a73b-85dc5ff49763,3,3
28,Harrison Floor 24,Harrison,9b95c471-053c-46ea-bc3b-d23bcad7a3a1,3,3
29,Hill House,Hill,82a00eb7-f70d-4a4c-9f0a-c2dafa4b67ea,16,16
30,Magee Amhurst,Quad,f6825dac-5a5a-4e4b-b66f-ea8226cbe78e,12,12
31,Mayer,Stouffer,6e3531d1-eebd-48b4-ad04-cf5983d42b02,8,8
32,Morgan,Quad,f249ca9f-ef84-4a35-9477-449b14612057,2,2
33,Rodin Floor 02,Rodin,7f25802d-31ad-4f80-ba26-d68a3f403aa8,3,3
34,Rodin Floor 04,Rodin,49e560fb-c1aa-4c98-a88a-cc9564481ec0,3,3
35,Rodin Floor 06,Rodin,701ce966-aa3c-4063-b3db-548ad89cb643,3,3
36,Rodin Floor 08,Rodin,4998a8a2-fb86-4900-bcb7-9d7cc6d9b938,3,3
37,Rodin Floor 10,Rodin,030c81c4-2300-4e8e-ae3a-303397a2e216,3,3
38,Rodin Floor 12,Rodin,c561f889-5898-41ba-99f5-2e6d4243e4d3,3,3
39,Rodin Floor 14,Rodin,2d211700-5b59-4c61-8922-991c0f7d7c15,3,3
40,Rodin Floor 16,Rodin,a10ede1d-044d-4852-87c7-eba7588c2497,3,3
41,Rodin Floor 18,Rodin,c3d3f9ae-792c-401c-8bd5-8c61fffe2ab1,3,3
42,Rodin Floor 20,Rodin,e88d3561-dce7-4188-89e7-b72cff7d69d6,3,3
43,Rodin Floor 22,Rodin,6b7dcd18-fe4e-4dc2-893f-35f0d7939c3c,3,3
44,Rodin Floor 24,Rodin,18397cd6-202e-4680-b82e-33ccd9ded1a7,3,3
45,Sansom East,Sansom,ad980c78-bf6d-429a-9a08-1b0899f83d62,16,16
46,Sansom West,Sansom,d1637690-098b-4eca-b48b-6d137207a38e,16,16
47,Stouffer Commons,Stouffer,d4848e7d-fdd0-4faa-b6bd-dc152842cf84,6,6
48,New College House,New College House,14b91b75-563b-4a7f-8b80-4efed338c29b,10,10
49,Harrison Floor 02,Harrison,78568718-85eb-420b-bc10-77154a685699,3,3
50,Van Pelt,Gregory,5d9b0588-c987-4d2c-9842-2ce3e9101577,6,6
51,Class of 1925,Gregory,78f20171-ab32-4650-a1ce-28ace7095790,4,4
52,Kings Court,KCEH,fdbd6c5f-cb26-486f-86cc-f0b95a7f2a8a,5,6
14089,English House,English House,14146,3,3
14082,"Gregory College House: Class of 1925""",Gregory College House: Class of 1925,14138,4,4
14085,Gregory College House: Van Pelt,Gregory College House: Van Pelt,14141,6,6
5249,Gutmann College House,Gutmann College House,5611,18,18
14099,Harnwell 10th Floor,Harnwell College House,14150,3,3
14100,Harnwell 12th Floor,Harnwell College House,14150,3,3
14101,Harnwell 14th Floor,Harnwell College House,14150,3,3
14102,Harnwell 16th Floor,Harnwell College House,14150,3,3
14103,Harnwell 18th Floor,Harnwell College House,14150,3,3
14104,Harnwell 20th Floor,Harnwell College House,14150,3,3
14105,Harnwell 22nd Floor,Harnwell College House,14150,3,3
14106,Harnwell 24th Floor,Harnwell College House,14150,3,3
14094,Harnwell 2nd Floor,Harnwell College House,14150,3,3
14095,Harnwell 4th Floor,Harnwell College House,14150,3,3
14096,Harnwell 6th Floor,Harnwell College House,14150,3,3
14098,Harnwell 8th Floor,Harnwell College House,14150,3,3
14111,Harrison 10th Floor,Harrison College House,14153,3,3
14112,Harrison 12th Floor ,Harrison College House,14153,3,3
14113,Harrison 14th Floor,Harrison College House,14153,3,3
14114,Harrison 16th Floor,Harrison College House,14153,3,3
14115,Harrison 18th Floor ,Harrison College House,14153,3,3
14116,Harrison 20th Floor,Harrison College House,14153,3,3
14117,Harrison 22nd Floor,Harrison College House,14153,3,3
14118,Harrison 24th Floor,Harrison College House,14153,3,3
14107,Harrison 2nd Floor,Harrison College House,14153,3,3
14108,Harrison 4th Floor,Harrison College House,14153,3,3
14109,Harrison 6th Floor,Harrison College House,14153,3,3
14110,Harrison 8th Floor,Harrison College House,14153,3,3
14090,Hill College House,Hill College House,14147,16,16
14091,King's Court,King's Court,14148,5,6
14092,Lauder,Lauder,14149,10,10
14078,Class of 28,Quad: Fisher College House,14655,0,0
14079,Craig,Quad: Fisher College House,14655,0,0
14080,Ashhurst - Magee,Quad: Riepe College House,14137,12,12
14076,Birthday - Bishop White,Quad: Riepe College House,14137,9,9
14077,Butcher - Chestnut,Quad: Ware College House,14656,0,0
14081,Morgan,Quad: Ware College House,14656,0,0
14123,Rodin 10th Floor,Rodin College House,14154,3,3
14124,Rodin 12th Floor,Rodin College House,14154,3,3
14125,Rodin 14th Floor,Rodin College House,14154,3,3
14126,Rodin 16th Floor,Rodin College House,14154,3,3
14127,Rodin 18th Floor,Rodin College House,14154,3,3
14128,Rodin 20th Floor,Rodin College House,14154,3,3
14129,Rodin 22nd Floor,Rodin College House,14154,3,3
14130,Rodin 24th Floor,Rodin College House,14154,3,3
14119,Rodin 2nd Floor,Rodin College House,14154,3,3
14120,Rodin 4th Floor,Rodin College House,14154,3,3
14121,Rodin 6th Floor,Rodin College House,14154,3,3
14122,Rodin 8th Floor,Rodin College House,14154,3,3
14084,Samson West,Samson West,14140,16,16
11373,Stouffer Commons,Stouffer College House,11693,4,4
14093,Stouffer Mayer,Stouffer College House,11693,8,8
14083,W.E.B. Du Bois College House,W.E.B. Du Bois College House,14139,6,6
11 changes: 6 additions & 5 deletions backend/laundry/management/commands/load_laundry_rooms.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,16 @@ def handle(self, *args, **kwargs):
reader = csv.reader(data)

for i, row in enumerate(reader):
hall_id, hall_name, location, uuid, total_washers, total_dryers = row
room_id, name, location, location_id, total_washers, total_dryers = row

LaundryRoom.objects.get_or_create(
hall_id=int(hall_id),
name=hall_name,
LaundryRoom.objects.create(
room_id=room_id,
name=name,
location=location,
uuid=uuid,
location_id=location_id,
total_washers=total_washers,
total_dryers=total_dryers,
new=True,
)

self.stdout.write("Uploaded Laundry Rooms!")
Loading
Loading