Skip to content

Latest commit

Β 

History

8 Commits

Folders and files

NameName
Last commit message
Last commit date
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

πŸ’‘ OfficeWatch

A live dashboard and Discord bot that watch every light and fan in a 3-room office, so nobody's boss has to ask "did someone leave the fan on again?" ever again.

Built for Techathon Nationals & Rover Summit (challenge: "Lights, Fans, Discord: The Boss's Big Idea"), hosted by IUT Robotics Society.


πŸ“‹ Table of Contents


Overview

The office has 3 rooms β€” a Drawing Room and two Work Rooms β€” each with 2 fans and 3 lights (15 devices total). People forget to turn things off when they leave, the electricity bill climbs, and nobody notices until it's too late.

This system gives the whole office one live, always-accurate picture of every device's state and power draw, accessible two ways:

  • πŸ–₯️ A real-time web dashboard β€” live status, power meter, and anomaly alerts, updating without a page refresh
  • πŸ€– A Discord bot β€” the same live data, answerable on demand from wherever the team already talks

Both interfaces read from one shared backend, so they can never show conflicting information.

Features

  • βœ… Live status for all 15 devices, grouped by room, updating in real time over WebSocket
  • βœ… Total + per-room power consumption meter (Watts) and an estimated daily kWh counter
  • βœ… Automatic alerts for devices left on after office hours (9 AM–5 PM) and rooms left fully on for 2+ continuous hours
  • βœ… Discord bot (!status, !room <name>, !usage) with humanized, friendly replies β€” never a raw data dump
  • βœ… Proactive Discord alert notifications pushed to a designated channel
  • βœ… Realistic, dynamic dummy data β€” no physical hardware required to run or judge this project
  • βœ… Graceful degradation everywhere a network boundary exists: WebSocket reconnect-with-backoff, Discord gateway auto-reconnect, and input validation on every route

Architecture

One backend process (Node.js) owns the only copy of device state. A software simulator drives realistic on/off and power-draw changes over time; a derived alert engine watches for anomalies; a WebSocket hub pushes live updates to the dashboard; and the Discord bot reads the exact same SQLite-backed store through a direct function call β€” not a network request β€” so the two interfaces are structurally incapable of disagreeing.

Full diagrams:

Full design rationale, data model, API contracts, and edge-case handling: docs/ARCHITECTURE.md.

Tech Stack

Layer Technology
Backend Node.js, Express
Real-time transport WebSocket (ws)
Discord bot discord.js β€” runs in the same process as the backend
Dashboard React
Data store Local SQLite file (node:sqlite) behind one store API, no separate database service
Hardware concept ESP32 + relays + ACS712 current sensor (Wokwi simulation β€” see below)

Getting Started

Prerequisites

  • Node.js 22+
  • A Discord bot token (Discord Developer Portal) with the MESSAGE CONTENT intent enabled
  • A Discord server where you can add the bot and designate an alerts channel

Installation

git clone <this-repo-url>
cd officewatch

# backend (includes the Discord bot β€” same process, not a separate install)
cd backend
npm install

# dashboard
cd ../dashboard
npm install

Configuration

Copy the example environment file and fill in your values:

cd backend
cp .env.example .env

See Environment Variables below for what each value does.

Running the system

# from /backend β€” starts REST API, WebSocket hub, simulator, alert engine,
# and the Discord bot together, in one process
npm start

The backend listens on PORT (default 3000). It also creates or reuses a local SQLite database at backend/data/officewatch.sqlite by default.

On a healthy startup, the bot logs Discord bot ready as <bot-tag> once Discord authentication completes. If startup fails with EADDRINUSE on 127.0.0.1:3000, stop the existing process on that port or change PORT in backend/.env before retrying.

Running the dashboard

cd dashboard
npm run dev

Open the printed local URL in your browser. The dashboard connects to the backend's /ws endpoint automatically and requests /api/status as a fallback if the socket hasn't connected within a few seconds.

Environment Variables

All variables are read by the backend only (/backend/.env) β€” the dashboard has none, since it only ever talks to the backend's public HTTP/WS surface.

Variable Required Default Description
DISCORD_BOT_TOKEN βœ… β€” Bot token from the Discord Developer Portal
DISCORD_ALERT_CHANNEL_ID βœ… β€” Channel ID where proactive alerts get posted
HOST No 127.0.0.1 Bind host for the backend server. Set 0.0.0.0 when you want LAN/container access.
PORT No 3000 Backend HTTP/WS port
TICK_INTERVAL_MS No 5000 Simulator tick interval
SQLITE_PATH No ./data/officewatch.sqlite SQLite database path for persisted device state and usage counters. Use :memory: for ephemeral test or demo runs.
NODE_ENV No β€” Set to production for a real deploy. Does not by itself control the debug route β€” see below.
ENABLE_DEBUG_ROUTES No false Must be explicitly set to true to enable /api/debug/force-alert. This is the only switch for that route β€” it is independent of NODE_ENV, so a production deploy is safe by default and a demo box can opt in explicitly without also having to run in dev mode.

Never commit a real .env file β€” it's excluded via .gitignore.

API Reference

Method Endpoint Description
GET /api/status Full state of all 15 devices, grouped by room
GET /api/room/:roomId Status of one room (drawing, work1, work2)
GET /api/usage Current total wattage + today's estimated kWh
GET /api/alerts Active and recently resolved alerts
GET /api/health Backend + simulator liveness check
GET /api/docs Human-readable backend API reference page
GET /api/docs.json OpenAPI 3.1 document for the backend contract
WS /ws Live push: full-state, state-update, alert-new, alert-resolved
POST /api/debug/force-alert (gated by ENABLE_DEBUG_ROUTES=true) Manufactures a real alert on demand β€” useful for demo recording, returns 404 otherwise
GET/POST /api/debug/simulation (gated by ENABLE_DEBUG_ROUTES=true) Dedicated demo simulation controls: pause/resume, preset scenarios, manual tick, and clock override

Full contract details (request/response shapes, validation rules, error handling): docs/ARCHITECTURE.md Β§5. Implementation-specific backend docs live in backend/API_DOCUMENTATION.md.

Demo simulation system

For presentations, set ENABLE_DEBUG_ROUTES=true and use /api/debug/simulation to load stable scenarios like:

  • after-hours-alert
  • prolonged-on-alert
  • mixed-anomaly
  • all-off
  • baseline

You can also pause the simulator, step one tick at a time, and override the effective local time so office-hours logic can be demonstrated on demand.

Discord Commands

Command Example What it does
!status !status or @OfficeWatch any fan running? Summary of all 3 rooms in one message
!room <name> !room work1 or @OfficeWatch status of Work Room 1 Status of a specific room β€” tolerant of natural phrasing
!usage !usage or @OfficeWatch how much power are we using? Current total wattage + today's estimated kWh

Responses are humanized sentences, not raw data dumps β€” the bot always replies with something useful even if a command is malformed. The bot supports both bang commands and direct @OfficeWatch mention-style questions for the same core actions.

The conversational layer stays grounded in the live backend data: it phrases replies more naturally, focuses on a single room when your message names one, and falls back to a short helpful suggestion instead of silently ignoring unclear prompts.

Quick verification after startup:

  • Confirm the backend logs Discord bot ready as <bot-tag>
  • Run !status
  • Run !room Work Room 1
  • Run !usage

Hardware / Circuit Concept

No physical hardware is required to run or judge this project β€” all device data is realistically simulated in software. For the required circuit schematic, this project designs (in Wokwi) a representative wiring concept for one room, showing how an ESP32 would read manual toggle switches, drive relays for real fans/lights, and sense actual current draw via an ACS712 sensor.

This schematic is a concept artifact. The deployed demo's live data comes entirely from the software simulator described in docs/ARCHITECTURE.md Β§4 β€” no physical or virtual hardware is required to run this project.

Project Structure

.
β”œβ”€β”€ backend/
β”‚   └── src/
β”‚       β”œβ”€β”€ config/officeLayout.js   # rooms, device counts, aliases, tick interval β€” single source of constants
β”‚       β”œβ”€β”€ deviceStore.js            # the one writer function + all reads, backed by SQLite persistence
β”‚       β”œβ”€β”€ simulator.js              # generates live device data
β”‚       β”œβ”€β”€ alertEngine.js            # derives anomalies from device state
β”‚       β”œβ”€β”€ routes/                   # REST endpoints
β”‚       β”œβ”€β”€ ws/hub.js                 # WebSocket broadcast
β”‚       β”œβ”€β”€ discord/                  # bot client + commands (same process as the API)
β”‚       └── server.js                 # single entrypoint
β”œβ”€β”€ dashboard/
β”‚   └── src/                          # React app
β”œβ”€β”€ diagrams/                         # all system + circuit diagrams, component list
β”œβ”€β”€ docs/
β”‚   β”œβ”€β”€ ARCHITECTURE.md               # full design documentation
β”‚   └── FRONTEND_BUILD_INSTRUCTIONS.md # dashboard build contract
β”œβ”€β”€ AGENTS.md                          # rules followed during AI-assisted development
└── .gitignore

Known Limitations

Documented explicitly rather than left for a reviewer to discover:

  • No authentication on the API/WebSocket/dashboard β€” acceptable for a demo, would be a first addition for production use.
  • Recent resolved alerts and Discord notification cooldowns are recalculated after a backend restart; only device state and usage counters are persisted.
  • Daylight Saving Time transitions aren't specially handled in the "2 hours continuously on" alert math.
  • One backend process handles everything by design, for guaranteed data consistency between the dashboard and bot β€” a production deployment at real scale would separate these with a shared data layer.

Full list with reasoning: docs/ARCHITECTURE.md Β§11.

Testing

cd backend
npm test

Covers the device store's write validation, alert-engine boundary conditions (e.g., 1h59m vs. 2h01m of continuous "on" time), and REST route input validation. See docs/ARCHITECTURE.md Β§10 for the full manual + automated validation plan, including WebSocket reconnect and Discord bot resilience checks.

Demo

πŸ“Ή Video walkthrough: <add your video link here>

License

<add your chosen license here β€” e.g. MIT>


Built for Techathon Nationals & Rover Summit by IUT Robotics Society.

Releases

Packages

Contributors

Languages