Skip to content

Commit 1e787e4

Browse files
authored
Merge branch 'main' into docs-page
2 parents 155aa91 + 7c7b24c commit 1e787e4

85 files changed

Lines changed: 10206 additions & 745 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/ci.yml

Lines changed: 46 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,25 +6,63 @@ on:
66
push:
77
branches: [ "main" ]
88

9+
concurrency:
10+
group: ci-${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
11+
cancel-in-progress: true
12+
13+
permissions:
14+
contents: read
15+
916
jobs:
10-
test:
17+
backend-tests:
1118
runs-on: ubuntu-latest
1219
steps:
1320
- name: Checkout
1421
uses: actions/checkout@v4
15-
22+
23+
- name: Set up Python
24+
uses: actions/setup-python@v5
25+
with:
26+
python-version: "3.11"
27+
1628
- name: Install UV
1729
uses: astral-sh/setup-uv@v4
1830
with:
1931
version: "latest"
20-
21-
- name: Set up Python
22-
run: uv python install 3.12
23-
32+
2433
- name: Install dependencies
2534
working-directory: ./svc
26-
run: uv sync
35+
run: uv sync --frozen
2736

2837
- name: Run tests
2938
working-directory: ./svc
30-
run: uv run pytest tests/ -v
39+
run: uv run pytest tests/ -v
40+
41+
frontend-checks:
42+
runs-on: ubuntu-latest
43+
steps:
44+
- name: Checkout
45+
uses: actions/checkout@v4
46+
47+
- name: Set up Node
48+
uses: actions/setup-node@v4
49+
with:
50+
node-version: "20"
51+
cache: "npm"
52+
cache-dependency-path: web/package-lock.json
53+
54+
- name: Install frontend dependencies
55+
working-directory: ./web
56+
run: npm ci
57+
58+
- name: Run frontend tests
59+
working-directory: ./web
60+
run: npm run test
61+
62+
- name: Run frontend typecheck
63+
working-directory: ./web
64+
run: npm run typecheck
65+
66+
- name: Build frontend
67+
working-directory: ./web
68+
run: npm run build
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
name: docker-builds
2+
3+
on:
4+
pull_request:
5+
branches: [ "main" ]
6+
push:
7+
branches: [ "main" ]
8+
9+
concurrency:
10+
group: docker-builds-${{ github.event.pull_request.number || github.ref }}
11+
cancel-in-progress: true
12+
13+
permissions:
14+
contents: read
15+
16+
jobs:
17+
docker-builds:
18+
runs-on: ubuntu-latest
19+
steps:
20+
- name: Checkout
21+
uses: actions/checkout@v4
22+
23+
- name: Validate compose file
24+
run: docker compose config --quiet
25+
26+
- name: Build combined app image
27+
run: docker build --tag glazing-control-app:${{ github.sha }} .
28+
29+
- name: Build compose services
30+
run: docker compose build

.gitignore

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -224,17 +224,29 @@ docs/TintSpecificAPIPages.pdf
224224
web/node_modules/
225225
web/dist/
226226

227+
# Service runtime/state data
227228
svc/data/audit.json
229+
svc/data/audit.db
230+
svc/data/*.db-journal
231+
svc/data/*.db-wal
232+
svc/data/*.db-shm
228233
svc/data/panels.json
229234
svc/data/panels_state.json
230235
svc/data/panels_config.json
231-
#svc/svc/data/window_mapping.json
232-
# Note: panels_config.json is tracked (structural data)
233-
# panels_state.json is ignored (runtime state)
236+
svc/data/routines/
234237

235238
svc/data/audit.db
236239
# audit.db is a SQLite database for the audit log, changes on run time, so ignore it for now
237240

238-
#just for sim output and routines to not be published
241+
#just for routines to not be published
239242
svc/data/routines/
243+
244+
# JETI simulator output (configured as either file or directory)
240245
svc/data/jeti_sim_output
246+
svc/data/jeti_sim_output/
247+
248+
# Vendor manuals, extracted text, and ad hoc sensor docs used for local AI context
249+
/docs/SensorDocs/
250+
251+
# Local temporary research repo / scratch workspace
252+
/.tmp_luox/

DEV-SETUP.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,7 @@ You should see the control interface
174174
# Use the app
175175

176176
1. The header shows service status
177-
2. Pick a group set a level press `Set group`
177+
2. Pick a group set a level press `Tint Group`
178178
3. Move a slider on any panel and press `Apply`
179179
4. Press `Refresh` in the header to reload state
180180

OVERVIEW.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -218,7 +218,7 @@ React + Vite front-end with an HMI-style control screen.
218218
- Stays a fixed max size in the middle of the screen
219219
- Tabs styled to match the Manage side panel tabs:
220220
- **Audit log** – table of command history
221-
- **Sensor log**placeholder for future sensor telemetry
221+
- **Sensor log**live sensor telemetry with filtering and CSV export
222222
- Props:
223223
- `isOpen` / `onClose`
224224
- `auditLogs`, `loading`, `error`

README.md

Lines changed: 56 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,58 +1,73 @@
1-
# Electrochromic Glazing Control System for Trailer Lab
1+
<div align="center">
2+
<h1>Glazing Control App</h1>
3+
<p><strong>A local-first control and scheduling system for the OSU Daylighting Innovation and Analysis Lab (DIAL) trailer.</strong></p>
4+
</div>
25

3-
A local first control and scheduling system for 18 facade electrochromic panels and 2 skylights in the OSU Radiant Lab trailer. Goals include safe manual control, study friendly scheduling, live status, and reliable operation on a constrained trailer network.
6+
![Dashboard Mockup](docs/images/dashboard.png)
7+
*A sleek interface for visualizing and controlling electrochromic panels and skylights.*
48

5-
## Working Agreements
9+
## Overview
610

7-
- Feature branches use `feature/<short-name>`
8-
- PR required with at least one reviewer
9-
- CI must be green before merge
10-
- Respond to PR reviews within 24 hours
11+
The **Glazing Control App** is the custom software backbone for the **[Daylighting Innovation and Analysis Lab (DIAL)](https://www.clotildepierson.com/facilities/dial)** at Oregon State University. DIAL is an off-the-grid mobile university research facility designed to study the impact of daylighting on human health and productivity.
1112

12-
## Project Board
13+
This app provides researchers and facility managers with a local-first system to intuitively manage, schedule, and monitor the facility's Halio electrochromic glazing.
1314

14-
We use a board with columns Backlog → Ready → In Progress → Review → Done.
15+
**The Problem:** Architectural researchers in DIAL need a reliable, study-friendly way to control two symmetrical test rooms (each with 9 windows and 1 skylight) without relying on external internet connections, especially when the mobile lab is deployed in remote or off-grid locations.
1516

16-
## Communication
17+
**The Solution:** By combining live status monitoring with an automated scheduling engine, the local software system provides precise environmental control.
1718

18-
Primary: Discord private server channel Team 76
19-
Secondary: email to partner or instructor
19+
## Key Features
2020

21-
## Getting Started
22-
An overview of the file structure:
23-
- `docs/` for design notes and meeting minutes
24-
- `sim/` for an API simulator used off site
25-
- `web/` for the researcher UI (Contains a README specific to the web interface)
26-
- `svc/` for the control service and queue (Contains a README specific to the backend service)
21+
- **Local-First Reliability:** Operates entirely on the local trailer network, provides responsiveness without depending on external internet access.
22+
- **Smart Scheduling Engine:** Create study-friendly, automated routines that adjust pane tinting based on time of day, minimizing manual intervention during research experiments.
23+
- **Live System Status:** Get real-time monitoring and visualization of all 18 Halio facade panels and 2 skylights from a single, unified dashboard.
24+
- **Sensor Integration Ready:** Built to analyze and manage DIAL's advanced setup of indoor and rooftop environmental sensors (including JETI spectroradiometers and EKO pyranometers).
25+
- **Safe Manual Override:** The safety-first manual override protocols allow the researchers to take direct control of individual panels.
2726

28-
## Watch for errors
29-
Run the watcher from `root`, `svc`, or `web`:
27+
![Sensor Integration](docs/images/sensors.png)
28+
*DIAL's advanced sensor suite provides real-time environmental data to the control system.*
3029

31-
```bash
32-
npm run watch
33-
```
30+
## How to Try It
3431

35-
Defaults by folder:
36-
- root: backend + frontend (`both`)
37-
- svc: backend only
38-
- web: frontend only
32+
To run the local control service and researcher UI on your machine:
3933

40-
Override the target in any folder:
34+
**Prerequisites:**
35+
- [Node.js](https://nodejs.org/) (v18+)
36+
- [Docker](https://www.docker.com/) (for full stack environment, optional)
4137

42-
```bash
43-
npm run watch -- backend
44-
npm run watch -- frontend
45-
npm run watch -- both
46-
```
38+
**Getting Started:**
4739

48-
## Acknowledgment
40+
1. **Clone the repository:**
41+
```bash
42+
git clone https://github.com/OSU-Radiant-Lab/GlazingControlApp.git
43+
cd GlazingControlApp
44+
```
4945

50-
- Aidan Lusk <luskai@oregonstate.edu>
51-
- Carlos Vasquez <vasqueca@oregonstate.edu>
52-
- Ian McKee <mckeei@oregonstate.edu>
53-
- Tyler Vincent <vincenty@oregonstate.edu>
54-
- Alexander Ulbrich <alexander.ulbrich@oregonstate.edu>
46+
2. **Start the development servers:**
47+
Run the watcher from the root directory to spin up both the frontend UI and the backend control service:
48+
```bash
49+
npm run watch -- both
50+
```
51+
*(To run separately, use `npm run watch -- frontend` or `npm run watch -- backend` on each).*
5552

56-
## License
53+
3. **Access the Application:**
54+
Open your browser and navigate to `http://localhost:3000` (or the port specified in your console output) to view the researcher UI.
5755

58-
GPL 3.0 License. See LICENSE.
56+
*Note: For real sensor deployment and site-specific facility notes, please refer to our [Setup Documentation](docs/real_sensor_setup.md).*
57+
58+
## The Team
59+
60+
This project was built by Team 76 for the OSU Radiant Lab.
61+
62+
- **Aidan Lusk** - [luskai@oregonstate.edu](mailto:luskai@oregonstate.edu)
63+
- **Carlos Vasquez** - [vasqueca@oregonstate.edu](mailto:vasqueca@oregonstate.edu)
64+
- **Ian McKee** - [mckeei@oregonstate.edu](mailto:mckeei@oregonstate.edu)
65+
- **Tyler Vincent** - [vincenty@oregonstate.edu](mailto:vincenty@oregonstate.edu)
66+
67+
**Feedback & Contributions:**
68+
Please open an issue on GitHub or reach out to the team directly via email. For internal team communication, refer to Discord channel Team 76.
69+
70+
---
71+
<div align="center">
72+
<p>Licensed under the <a href="LICENSE">GPL 3.0 License</a>.</p>
73+
</div>

docker-compose.yml

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
version: '3.8'
2+
3+
services:
4+
svc:
5+
build:
6+
context: ./svc
7+
dockerfile: Dockerfile
8+
container_name: glazing-svc
9+
ports:
10+
- "8000:8000"
11+
volumes:
12+
- ./svc/data:/app/data
13+
environment:
14+
- SVC_HOST=0.0.0.0
15+
- SVC_PORT=8000
16+
- UVICORN_RELOAD=false
17+
restart: unless-stopped
18+
19+
web:
20+
build:
21+
context: ./web
22+
dockerfile: Dockerfile
23+
args:
24+
# Ok since we are only running locally, we can just use localhost
25+
- VITE_API_BASE=http://localhost:8000
26+
container_name: glazing-web
27+
ports:
28+
- "80:80"
29+
depends_on:
30+
- svc
31+
restart: unless-stopped
32+
33+

docs/images/dashboard.png

158 KB
Loading

docs/images/sensors.png

74.1 KB
Loading

docs/on_site_sensor_checklist.md

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
# On-Site Sensor Checklist
2+
3+
Use this at the trailer/lab PC after the hardware is physically installed.
4+
5+
## Connection Order
6+
7+
1. Connect each `T-10A` head chain to its T-10A body.
8+
2. If a T-10A body has multiple heads, connect external power to that setup.
9+
3. Connect each `T-10A` body to the PC by USB.
10+
4. Connect each JETI device to the PC by USB.
11+
5. If the JETI path will use file mode, confirm the PC software is configured to write a live `.cap` file or folder.
12+
6. If the JETI path will use direct serial mode, confirm the JETI USB driver is installed and a COM port appears in Windows.
13+
7. Connect the EKO `MS-90` and optional `MS-80S` to the `C-BOX`.
14+
8. Connect `C-BOX` output power and RS-485 wiring.
15+
9. Connect the USB-to-RS485 adapter from the `C-BOX` output side to the PC.
16+
17+
## Windows Checks
18+
19+
1. Open Device Manager.
20+
2. Record the COM port for each `T-10A` body.
21+
3. Record the COM port for each JETI device that will use direct serial mode.
22+
4. Record the COM port for the USB-RS485 adapter used by the `C-BOX`.
23+
5. If a JETI device is missing, install the JETI USB driver and reconnect it.
24+
25+
## Update `svc/data/sensors_config.json`
26+
27+
1. Set `t10a[].port` to the actual T-10A COM port.
28+
2. Set `t10a[].heads[].head_no` to the actual physical T-10A adaptor/head ID.
29+
3. Set `jeti_spectraval[].transport` to either `file` or `serial_scpi`.
30+
4. If JETI uses file mode, set `jeti_spectraval[].output_path` to the actual live `.cap` file or folder.
31+
5. If JETI uses serial mode, set `jeti_spectraval[].port` to the JETI COM port.
32+
6. If JETI uses serial mode, set `jeti_spectraval[].baudrate`:
33+
- `921600` for `spectraval 1511`
34+
- `115200` for `specbos 1211-2`
35+
7. Set `eko_ms90_plus[].port` to the COM port of the USB-RS485 adapter.
36+
37+
## Start The Backend
38+
39+
```powershell
40+
cd svc
41+
$env:SVC_MODE = "real"
42+
uv run python main.py
43+
```
44+
45+
Use `SENSORS_CONFIG_FILE` only if you are not using the default `svc/data/sensors_config.json`.
46+
47+
## Acceptance Checks
48+
49+
```powershell
50+
Invoke-RestMethod http://127.0.0.1:8000/sensors
51+
Invoke-RestMethod http://127.0.0.1:8000/metrics/latest
52+
```
53+
54+
Verify:
55+
56+
- T-10A sensors report `lux`
57+
- JETI sensors report `lux` plus color/spectral metrics
58+
- EKO reports `ghi_w_m2`, `dni_w_m2`, `dhi_w_m2`, and sun position data
59+
60+
Then open the HMI and confirm:
61+
62+
- live sensor cards are populated
63+
- live graphs update
64+
- `Logs -> Sensor log` is filling with new rows
65+
- sensor CSV export works
66+
67+
For the full step-by-step connection instructions for each sensor and each supported method, use [`docs/real_sensor_setup.md`](./real_sensor_setup.md).
68+
69+
## If Something Fails
70+
71+
- No T-10A data:
72+
- re-check USB COM port
73+
- verify head IDs
74+
- verify straight CAT5 and external power for multi-point mode
75+
- No JETI data:
76+
- re-check driver install
77+
- confirm the PC measurement software is writing to the configured `output_path`, or
78+
- confirm COM port and baudrate for serial mode
79+
- No EKO data:
80+
- swap RS-485 `A/B`
81+
- verify `12 VDC` power and fuse
82+
- verify `slave_address`
83+
- try a different `float_byte_order` if values are present but incorrect

0 commit comments

Comments
 (0)