All projects

WashingMachineDormitory

★ 0 stars↓ 0 downloads
Open on GitHub ↗

README.md

Laundry Status Web

A simple web app for a dorm: it shows whether the washing machine is in use or not, and until what time.

What it does

  • Displays the current status: free/occupied.
  • Shows which room is using the machine.
  • Shows the time until the machine is no longer in use.
  • Displays a countdown.
  • Allows you to quickly reserve a machine for 30/45/60/90 minutes.
  • Allows you to specify your own duration in minutes.
  • Suggests a list of rooms based on your history.
  • Prompts for a PIN in a dialog box after you tap an action.
  • Prevents rebooking if the machine is already booked.
  • Allows you to manually release a machine.
  • Protects status changes with a PIN code.
  • Keeps a history of completed wash cycles.

Technologies

  • Node.js + Express
  • Pure HTML/CSS/JavaScript (no framework)
  • Status and history stored in JSON files (data/status.json, data/history.json)

Variables and files

  • STATUS_PIN - PIN code for changing status (it is recommended to set it via .env or environment variables)
  • TELEGRAM_BOT_TOKEN - Telegram bot token (optional, for notifications)
  • TELEGRAM_CHAT_ID - Group chat/channel ID for notifications
  • TELEGRAM_API_BASE_URL - Telegram API base URL (default https://api.telegram.org)
  • config.json - Local fallback for the PIN; do not store it in Git
  • data/status.json, data/history.json - application runtime data—do not store it in Git

If config.json it happens to be created as a directory, you can skip using it entirely and set the PIN only via STATUS_PIN.

Running locally

  1. Install dependencies:
npm install
  1. Start the server:
npm start

Default PIN: 1234. The recommended way to change it is via the environment variable STATUS_PIN.

  1. Open in a browser:
http://localhost:3000

Run on the server

  1. Copy the project to the server.
  2. Install Node.js 18+.
  3. Run:
npm install
STATUS_PIN=myStrongPin PORT=3000 npm start

If you're using Nginx/Caddy, configure the reverse proxy to port 3000.

Full installation on a clean Ubuntu server

Below is the procedure using Docker Compose (recommended).

0) DNS Setup

  1. For the domain (for example, wash.example.com) add AA A record pointing to the server’s IP address.
  2. Wait for the DNS to update.

1) Update the system

sudo apt update && sudo apt upgrade -y

2) Install Docker and the Docker Compose plugin

sudo apt install -y ca-certificates curl gnupg
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
sudo chmod a+r /etc/apt/keyrings/docker.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo $VERSION_CODENAME) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
sudo usermod -aG docker $USER

Log out (or newgrp docker), then check:

docker --version
docker compose version

3) Copy the project to the server

Option via Git:

git clone <URL_ВАШЕГО_РЕПО> laundry-status-web
cd laundry-status-web

Or download the archive and navigate to the project folder.

4) Set up the environment and start the container

cp .env.example .env

Open .env and set a complex PIN:

STATUS_PIN=очень_сложный_pin

Start:

docker compose up -d --build

Verification:

docker compose ps
docker compose logs -f

5) Install Nginx

sudo apt install -y nginx
sudo systemctl enable nginx
sudo systemctl start nginx

6) Configure a reverse proxy for the domain

Create a file:

sudo nano /etc/nginx/sites-available/laundry-status

Content:

server {
    listen 80;
    server_name wash.example.com;

    location / {
        proxy_pass http://127.0.0.1:3000;
        proxy_http_version 1.1;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

Enable:

sudo ln -s /etc/nginx/sites-available/laundry-status /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx

7) Enable HTTPS (Let's Encrypt)

sudo apt install -y certbot python3-certbot-nginx
sudo certbot --nginx -d wash.example.com

Check for automatic certificate renewal:

sudo systemctl status certbot.timer

8) Open a port in the firewall (if UFW is enabled)

sudo ufw allow OpenSSH
sudo ufw allow 'Nginx Full'
sudo ufw enable
sudo ufw status

9) Update the application

cd laundry-status-web
git pull
docker compose up -d --build

10) Useful diagnostics

docker compose ps
docker compose logs -f
sudo nginx -t
sudo journalctl -u nginx -f

Docker Compose

  1. Copy the example env file:
cp .env.example .env
  1. If necessary, change the PIN in .env:
STATUS_PIN=твой_pin

For Telegram notifications, add the following to .env:

TELEGRAM_BOT_TOKEN=123456789:ABCDEF...
TELEGRAM_CHAT_ID=-1001234567890
TELEGRAM_API_BASE_URL=https://api.telegram.org

If Telegram is only accessible on the server through your proxy (for example, via x-ui), set TELEGRAM_API_BASE_URL to this proxy URL.

  1. Run it via Docker Compose:
docker compose up -d --build
  1. Open in a browser:
http://localhost:3000

API

  • GET /api/status - Get status
  • GET /api/history?limit=20 - Get wash history
  • GET /api/rooms?limit=40 - Get a list of rooms for hints
  • POST /api/status/occupy - Reserve a machine
    • body: { "minutes": 60, "occupiedRoom": "417", "pin": "1234" }
    • occupiedRoom: up to 16 characters, at least 1 digit; letters, digits, and-/_//
    • if the machine is occupied: 409 Conflict
  • POST /api/status/release - free up the machine
    • body: { "pin": "1234" }

History is stored in data/history.json, current status in data/status.json.

Telegram bot: notifications in the group chat

The app can send notifications about changes to the machine's status via Telegram.

What is sent

  • When the machine is occupied (occupied)
  • When the machine is manually released (released)
  • When the machine is automatically released by a timer

How to set it up

  1. Create a bot via @BotFather and get a token.
  2. Add the bot to your group chat (group or channel).
  3. Grant the bot permission to send messages (for a channel, add it as an administrator).
  4. Find out chat_id:
    • send any message to the chat,
    • open it in your browser https://api.telegram.org/bot<YOUR_BOT_TOKEN>/getUpdates,
    • find chat.id.
  5. Write down TELEGRAM_BOT_TOKEN and TELEGRAM_CHAT_ID in .env.
    • If you're using Telegram proxying via x-ui/your gateway, set TELEGRAM_API_BASE_URL.
  6. Restart the service:
docker compose up -d --force-recreate

If TELEGRAM_BOT_TOKEN or TELEGRAM_CHAT_ID are not set, notifications are disabled.

For the x-ui/Telegram API proxy:

  • Specify, for example, TELEGRAM_API_BASE_URL=https://your-domain.example/telegram.
  • The server must proxy the path /bot<TOKEN>/sendMessage to the Telegram Bot API.

Releases

No releases yet.

Open issues

No open issues 🎉

This page was machine-translated from Russian

RU