Real-time monitoring system for 300+ computers across university laboratories.
It allows visualization of the current state of all PCs — FREE, IN_SESSION, or OFFLINE — distributed among different university labs.
Service (Backend): Go + Gorilla WebSocket + Windows Services API
- Developer: Sergio Silva
Frontend: React + TypeScript + Vite + WebSocket API
- Developer: Tulio Riaño
- Source Code: GitHub | Occupied-Frontend
- Architecture
- Components
- Requirements
- Quick Installation
- Gateway Installation
- Agent Installation
- Configuration
- Usage
- API
- Mass Deployment
- Troubleshooting
- Roadmap
- License
- Contact
- Credits
- FREE: PC is powered on and available for use
- IN_SESSION: PC is currently in use by a user
- OFFLINE: PC is powered off or not connected
- Gateway Server (Go): Central WebSocket server that receives heartbeats from agents
- Agent Client (Go): Windows service running on each PC
- Frontend Dashboard (React): Web interface for real-time status visualization
| Laboratory | Range PC | Range IP |
|---|---|---|
| B0-Libre | Sistemas25 – Sistemas49, Sistemas78 – Sistemas80 | 10.2.67.25 – 10.2.67.49, 10.2.67.78 – 10.2.67.79, 81 |
| Plataformas | Sistemas01 – Sistemas24 | 10.2.67.1 – 10.2.67.24 |
| Ing-Software | Sistemas50 – Sistemas73 | 10.2.67.50 – 10.2.67.73 |
| Redes | Sistemas101 – Sistemas116 | 10.2.67.101 – 10.2.67.116 |
| Interactiva | Interactiva01 – Interactiva08 | 10.2.67.151 – 10.2.67.158 |
| Multimedia | Sistemas160 – Sistemas175 | 10.2.67.161 – 10.2.67.172, 175 |
| Fundamentos | Sistemas176 – Sistemas199 | 10.2.67.176 – 10.2.67.199 |
| Juegos | Sistemas200 – Sistemas217 | 10.2.67.200 – 10.2.67.218 |
| EDFI | Sistemas240, Sistemas301 – Sistemas330, Sistemas343, Sistemas345, Sistemas354, Sistemas389 | |
| 10.2.68.1 - 30 | ||
| (Profe 10.2.68.50) |
| | NEW Arq-Sistemas | Sistemas351 – Sistemas373 | 10.2.68.51 – 73 |
- Puerto por defecto:
:8080 - Endpoints:
GET /- Pagina HTML simple de debugGET /api/devices- API REST con lista de dispositivosWS /ws/agent- WebSocket para conexion de agentesWS /ws/client- WebSocket para dashboards
- Servicio de Windows con auto-inicio
- Envia heartbeats cada 5 segundos
- Reconexion automatica con exponential backoff
- Detecta IP local automaticamente
- React + Vite
- WebSocket para actualizaciones en tiempo real
- Visualizacion de estado de todos los equipos
- Go 1.20+
- Sistema operativo: Linux/Windows
- Puerto 8080 abierto en firewall
- Dependencias:
go get github.com/gorilla/websocket
- Go 1.20+
- Windows 10/11
- Privilegios de Administrador (para instalacion)
- Dependencias:
go get github.com/gorilla/websocket go get golang.org/x/sys/windows/svc go get golang.org/x/sys/windows/svc/eventlog
- Node.js 18+
- npm o yarn
- Navegador moderno (Chrome, Firefox, Edge)
git clone https://github.com/tu-universidad/labinfo.git
cd labinfocd server
go run server.goEl servidor estara disponible en http://localhost:8080
cd client
go run client.goAbre tu navegador en http://localhost:8080
cd server
go build -o labinfo-gateway server.goUsar NSSM (Non-Sucking Service Manager):
# Descargar NSSM desde https://nssm.cc/download
nssm install LabInfoGateway "C:\LabInfo\labinfo-gateway.exe"
nssm set LabInfoGateway Description "LabInfo Gateway Server"
nssm set LabInfoGateway Start SERVICE_AUTO_START
nssm start LabInfoGatewaycd client
go build -o labinfo-agent.exe client_service.go# Abrir PowerShell como Administrador
.\install.ps1 -ServerURL "ws://192.168.1.100:8080/ws/agent"El script automaticamente:
- Crea directorios necesarios
- Copia el ejecutable
- Configura variables de entorno
- Instala el servicio de Windows
- Inicia el servicio
Get-Service LabInfoAgent
Get-Content "C:\ProgramData\LabInfo\agent.log" -Tail 20# 1. Crear directorios
mkdir "C:\Program Files\LabInfo"
mkdir "C:\ProgramData\LabInfo"
# 2. Copiar ejecutable
Copy-Item labinfo-agent.exe "C:\Program Files\LabInfo\labinfo-agent.exe"
# 3. Configurar URL del servidor
[Environment]::SetEnvironmentVariable("LABINFO_WS", "ws://192.168.1.100:8080/ws/agent", "Machine")
# 4. Crear servicio
sc.exe create LabInfoAgent binPath= "C:\Program Files\LabInfo\labinfo-agent.exe" start= auto DisplayName= "LabInfo Monitoring Agent"
# 5. Iniciar servicio
Start-Service LabInfoAgent# Ejecutar script de desinstalacion
C:\Program Files\LabInfo\uninstall.ps1
# O manualmente:
Stop-Service LabInfoAgent
sc.exe delete LabInfoAgent
Remove-Item "C:\Program Files\LabInfo" -Recurse -Force
[Environment]::SetEnvironmentVariable("LABINFO_WS", $null, "Machine")LABINFO_ADDR- Direccion y puerto del servidor (default::8080)export LABINFO_ADDR=":9000"
LABINFO_WS- URL del WebSocket del gateway (default:ws://localhost:8080/ws/agent)[Environment]::SetEnvironmentVariable("LABINFO_WS", "ws://192.168.1.100:8080/ws/agent", "Machine")
New-NetFirewallRule -DisplayName "LabInfo Gateway" -Direction Inbound -Protocol TCP -LocalPort 8080 -Action Allowsudo iptables -A INPUT -p tcp --dport 8080 -j ACCEPT
sudo iptables-save > /etc/iptables/rules.v4# Ver logs en tiempo real (Linux)
journalctl -u labinfo-gateway -f
# Reiniciar servicio
sudo systemctl restart labinfo-gateway
# Ver estado
sudo systemctl status labinfo-gateway# Ver estado del servicio
Get-Service LabInfoAgent
# Ver logs en tiempo real
Get-Content "C:\ProgramData\LabInfo\agent.log" -Wait -Tail 20
# Reiniciar servicio
Restart-Service LabInfoAgent
# Detener servicio
Stop-Service LabInfoAgent
# Iniciar servicio
Start-Service LabInfoAgent# Instalar wscat (si no esta instalado)
npm install -g wscat
# Conectar como agente
wscat -c ws://localhost:8080/ws/agent
# Enviar mensaje de ejemplo:
{"agent_id":"test-pc","ip":"192.168.1.50","state":"FREE","timestamp":"2025-10-17T12:00:00Z"}
# Conectar como dashboard
wscat -c ws://localhost:8080/ws/clientObtiene la lista de todos los dispositivos conectados.
Response:
[
{
"agent_id": "PC-LAB-A-01",
"ip": "192.168.1.10",
"lab_id": "LAB-A",
"state": "FREE",
"username": "",
"timestamp": "2025-10-17T15:30:45Z",
"version": "mvp-0.1"
},
{
"agent_id": "PC-LAB-A-02",
"ip": "192.168.1.11",
"state": "IN_SESSION",
"username": "john.doe",
"timestamp": "2025-10-17T15:30:46Z"
}
]Message Format:
{
"agent_id": "PC-LAB-A-01",
"ip": "192.168.1.10",
"lab_id": "LAB-A",
"state": "FREE",
"username": "john.doe",
"timestamp": "2025-10-17T15:30:45Z",
"version": "mvp-0.1"
}Server ACK:
{
"status": "ok"
}Initial Snapshot:
{
"type": "snapshot",
"devices": [
{
"agent_id": "PC-LAB-A-01",
"ip": "192.168.1.10",
"state": "FREE",
"timestamp": "2025-10-17T15:30:45Z"
}
]
}State Change Event:
{
"type": "state_change",
"device": {
"agent_id": "PC-LAB-A-01",
"ip": "192.168.1.10",
"state": "IN_SESSION",
"username": "john.doe",
"timestamp": "2025-10-17T15:31:00Z"
}
}-
Compila el agente y copia los archivos a un share de red:
\\servidor\labinfo\labinfo-agent.exe \\servidor\labinfo\install.ps1 -
Crea un GPO:
- Computer Configuration → Policies → Windows Settings → Scripts
- Startup Scripts → Add → PowerShell Scripts
- Script Name:
\\servidor\labinfo\install.ps1 - Script Parameters:
-ServerURL "ws://192.168.1.100:8080/ws/agent"
-
Vincula el GPO a las OUs de los laboratorios
-
Fuerza actualizacion en un PC de prueba:
gpupdate /force
# Crear archivo con lista de PCs
$computers = Get-Content "equipos.txt"
# Despliegue en paralelo
$computers | ForEach-Object -Parallel {
$computer = $_
try {
# Copiar archivos
Copy-Item "labinfo-agent.exe" "\\$computer\C$\Temp\" -Force
Copy-Item "install.ps1" "\\$computer\C$\Temp\" -Force
# Ejecutar instalacion remota
Invoke-Command -ComputerName $computer -ScriptBlock {
Set-Location C:\Temp
.\install.ps1 -ServerURL "ws://192.168.1.100:8080/ws/agent"
}
Write-Host "OK: $computer" -ForegroundColor Green
}
catch {
Write-Host "ERROR: $computer - $_" -ForegroundColor Red
}
} -ThrottleLimit 10-
Crea un paquete de aplicacion con:
labinfo-agent.exe- Script de instalacion personalizado
-
Configura deteccion:
- Registry:
HKLM\SYSTEM\CurrentControlSet\Services\LabInfoAgent - O File:
C:\Program Files\LabInfo\labinfo-agent.exe
- Registry:
-
Despliega a las colecciones de dispositivos de laboratorios
Sintoma: El agente muestra errores de conexion en los logs.
Solucion:
-
Verificar conectividad de red:
Test-NetConnection -ComputerName 192.168.1.100 -Port 8080
-
Verificar URL configurada:
[Environment]::GetEnvironmentVariable("LABINFO_WS", "Machine")
-
Verificar firewall:
Get-NetFirewallRule | Where-Object {$_.DisplayName -like "*8080*"}
-
Ver logs del agente:
Get-Content "C:\ProgramData\LabInfo\agent.log" -Tail 50
Sintoma: El dashboard muestra datos obsoletos o vacios.
Solucion:
-
Verificar que el servidor esta corriendo:
curl http://192.168.1.100:8080/api/devices
-
Abrir DevTools en el navegador:
- Network → WS → Verificar conexion WebSocket
- Console → Ver errores JavaScript
-
Verificar logs del servidor:
# Buscar "dashboard client connected" journalctl -u labinfo-gateway | grep "dashboard client"
-
Probar conexion manual:
wscat -c ws://192.168.1.100:8080/ws/client
Sintoma: Despues de reiniciar el PC, el servicio no esta corriendo.
Solucion:
-
Verificar configuracion de inicio:
Get-Service LabInfoAgent | Select-Object Name, Status, StartType
-
Debe mostrar
StartType: Automatic -
Si no, configurar:
Set-Service -Name LabInfoAgent -StartupType Automatic
-
Ver eventos del sistema:
Get-EventLog -LogName System | Where-Object {$_.Source -eq "Service Control Manager" -and $_.Message -like "*LabInfo*"}
Sintoma: El Gateway consume muchos recursos.
Causa: 400 agentes × 80 msg/s → broadcast a multiples dashboards.
Soluciones:
- Implementar rate limiting en broadcast
- Agregar compresion WebSocket
- Solo enviar cambios reales (no heartbeats sin cambio)
- Implementar Redis para estado compartido
Sintoma: Archivo agent.log vacio o inexistente.
Solucion:
-
Verificar permisos en el directorio:
icacls "C:\ProgramData\LabInfo" -
Ejecutar servicio con permisos de sistema:
sc.exe config LabInfoAgent obj= LocalSystem
-
Verificar que el directorio existe:
Test-Path "C:\ProgramData\LabInfo"
- WebSocket Gateway in Go
- Windows Agent as a service
- Basic React Dashboard
- States: FREE, IN_SESSION, OFFLINE
- Auto-reconnection with exponential backoff
- Automated installation script
- Thread-safe operations (no race conditions)
- Consistent state sync (snapshots, not accumulation)
- Unique client identification (by IP + hostname)
- Automated testing (race detection scripts)
- Persistence: Redis for current state + PostgreSQL for history
- Authentication: JWT or OAuth2 for the dashboard
- Metrics: Prometheus + Grafana
- Intelligent state detection (via WMI queries)
- Automatic Lab ID (detect by IP range or config)
- Notifications: Alerts when labs are full/empty
- Extended API: Filters by lab, statistics, reports
Critical Issues Resolved:
- ✅ Race Condition Fix: Eliminated
concurrent map writespanics in server - ✅ State Accumulation Fix: Frontend no longer accumulates counters (1 client = 1 display, not N)
- ✅ Unique Identification: Added
agent_idandipto broadcasts for proper client tracking - ✅ Thread-Safe Broadcast: Atomic region with single lock/unlock in
broadcastUpdate() - ✅ Snapshot-Based Updates: Dashboard receives full snapshots (not incremental changes)
- ✅ Auto-Recovery: State drift auto-corrects on next snapshot
Documentation Added:
- 📄
RACE_CONDITION_FIX.md- Technical deep-dive - 📄
EXECUTIVE_SUMMARY.md- High-level overview - 📄
QUICK_VERIFICATION.md- Testing guide - 🧪
test_race_conditions.ps1/sh- Automated test scripts
Before: 1 client changing state 10 times = frontend shows 10 clients ❌
After: 1 client changing state 100 times = frontend shows 1 client ✅
See RACE_CONDITION_FIX.md for detailed technical analysis.
-
Persistence: Redis for current state + PostgreSQL for history
-
Authentication: JWT or OAuth2 for the dashboard
-
Metrics: Prometheus + Grafana
-
Intelligent state detection (via WMI queries)
-
Automatic Lab ID (detect by IP range or config)
-
Notifications: Alerts when labs are full/empty
-
High Availability: Multiple gateway instances with Redis Pub/Sub
-
Machine Learning: Lab usage prediction
-
Mobile App: Native iOS/Android
-
SSO Integration: LDAP/Active Directory
-
Advanced Dashboard: Lab maps, reservations, heatmaps
-
Webhooks: Integration with external systems
Apache License 2.0 – See the LICENCE file for details.
- Development Team: ti@universidad.edu
- Repository: https://github.com/universidad/labinfo
- Issues: https://github.com/universidad/labinfo/issues
Team: Sergio Silva & Tulio Riaño
© 2025 Computer Lab, Escuela Colombiana de Ingeniería Julio Garavito.
All rights reserved.
