diff --git a/SETUP.md b/SETUP.md new file mode 100644 index 0000000..4a38548 --- /dev/null +++ b/SETUP.md @@ -0,0 +1,183 @@ +# IPMI Controller - Setup Guide + +## Prerequisites + +- Dell server with IPMI (iDRAC) enabled +- Linux host (Ubuntu/Debian recommended) +- Python 3.10+ +- ipmitool + +## Installation + +### 1. Install IPMI Controller + +On your management server (where you run the controller): + +```bash +git clone https://github.com/yourusername/ipmi-controller.git +cd ipmi-controller +pip install -r requirements.txt +``` + +### 2. Install ipmitool + +```bash +sudo apt-get update +sudo apt-get install -y ipmitool +``` + +### 3. Run the Controller + +```bash +python3 web_server.py +``` + +Open `http://your-server:8000` in browser. + +## Initial Setup + +1. **Complete the Setup Wizard:** + - Create admin account + - Enter IPMI credentials + - IP: Your Dell server's IPMI IP + - Username: Usually "root" + - Password: Your IPMI password + - Port: 623 (default) + +2. **Login** with your new admin credentials + +## lm-sensors HTTP Server (Optional but Recommended) + +For better temperature monitoring (including PCIe cards), set up lm-sensors on your Dell server: + +### Option A: Automated Setup + +On your **Dell/Proxmox server** (not the controller): + +```bash +# Download and run setup script +curl -O https://raw.githubusercontent.com/yourusername/ipmi-controller/main/setup-sensors-server.sh +chmod +x setup-sensors-server.sh +sudo ./setup-sensors-server.sh +``` + +### Option B: Manual Setup + +1. **Install lm-sensors:** +```bash +sudo apt-get install -y lm-sensors netcat-openbsd +``` + +2. **Detect sensors:** +```bash +sudo sensors-detect --auto +``` + +3. **Test sensors:** +```bash +sensors +``` + +4. **Create HTTP server script** (`/usr/local/bin/sensors-http-server.sh`): +```bash +#!/bin/bash +PORT=${1:-8888} +while true; do + { + echo -e "HTTP/1.1 200 OK\r" + echo -e "Content-Type: text/plain\r" + echo -e "Access-Control-Allow-Origin: *\r" + echo -e "\r" + sensors -u 2>/dev/null || echo "Error" + } | nc -l -p "$PORT" -q 1 +done +``` + +5. **Make executable:** +```bash +chmod +x /usr/local/bin/sensors-http-server.sh +``` + +6. **Create systemd service** (`/etc/systemd/system/sensors-http.service`): +```ini +[Unit] +Description=lm-sensors HTTP Server +After=network.target + +[Service] +Type=simple +ExecStart=/usr/local/bin/sensors-http-server.sh 8888 +Restart=always +User=root + +[Install] +WantedBy=multi-user.target +``` + +7. **Enable and start:** +```bash +sudo systemctl daemon-reload +sudo systemctl enable sensors-http +sudo systemctl start sensors-http +``` + +8. **Test:** +```bash +curl http://$(hostname -I | awk '{print $1}'):8888 +``` + +### Configure IPMI Controller + +1. Go to **Settings** → **HTTP** tab +2. Enable "HTTP Sensor" +3. Enter URL: `http://your-dell-server-ip:8888` +4. Save + +## Docker Deployment + +```bash +docker build -t ipmi-controller . +docker run -d \ + -p 8000:8000 \ + -v $(pwd)/data:/app/data \ + --name ipmi-controller \ + ipmi-controller +``` + +## Troubleshooting + +### IPMI Connection Failed +- Verify IPMI IP is correct +- Check IPMI username/password +- Ensure IPMI is enabled in BIOS/iDRAC +- Test manually: `ipmitool -I lanplus -H -U -P mc info` + +### No Temperature Data +- Check if lm-sensors is installed on Dell server +- Run `sensors` to verify it works +- Check HTTP endpoint: `curl http://dell-ip:8888` + +### Service Won't Start +```bash +# Check logs +sudo journalctl -u sensors-http -f + +# Check if port is in use +sudo netstat -tlnp | grep 8888 +``` + +## Security Notes + +- Change default password after first login +- Use HTTPS/reverse proxy for production +- Firewall port 8000 to internal network only +- HTTP sensor endpoint is read-only + +## Updating + +```bash +cd ipmi-controller +git pull +pip install -r requirements.txt +# Restart the service +``` diff --git a/data/config.json b/data/config.json index bc78da6..b22f3b3 100644 --- a/data/config.json +++ b/data/config.json @@ -3,8 +3,8 @@ "ipmi_username": "root", "ipmi_password": "calvin", "ipmi_port": 623, - "http_sensor_enabled": false, - "http_sensor_url": "", + "http_sensor_enabled": true, + "http_sensor_url": "http://192.168.5.200:8888", "http_sensor_timeout": 10, "enabled": true, "poll_interval": 10, @@ -16,7 +16,7 @@ "panic_on_no_data": true, "no_data_timeout": 60, "primary_sensor": "cpu", - "sensor_preference": "ipmi", + "sensor_preference": "auto", "fans": {}, "fan_groups": {}, "fan_curves": { diff --git a/server.log b/server.log index cfdc567..b12e2a4 100644 --- a/server.log +++ b/server.log @@ -1,61 +1,147 @@ -INFO: Started server process [896609] +INFO: Started server process [18785] INFO: Waiting for application startup. INFO: Application startup complete. INFO: Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to quit) -INFO: 192.168.5.30:63112 - "GET /api/status HTTP/1.1" 401 Unauthorized -INFO: 192.168.5.30:63112 - "GET /login HTTP/1.1" 200 OK +INFO: 192.168.5.30:50547 - "GET /api/status HTTP/1.1" 401 Unauthorized +INFO: 192.168.5.30:50547 - "GET /login HTTP/1.1" 200 OK /home/devmatrix/projects/fan-controller-v2/web_server.py:149: DeprecationWarning: datetime.datetime.utcnow() is deprecated and scheduled for removal in a future version. Use timezone-aware objects to represent datetimes in UTC: datetime.datetime.now(datetime.UTC). self._sessions[token] = (username, datetime.utcnow() + timedelta(days=7)) -INFO: 192.168.5.30:49451 - "POST /api/auth/login HTTP/1.1" 200 OK -INFO: 192.168.5.30:49451 - "GET / HTTP/1.1" 200 OK +INFO: 192.168.5.30:64565 - "POST /api/auth/login HTTP/1.1" 200 OK +INFO: 192.168.5.30:64565 - "GET / HTTP/1.1" 200 OK /home/devmatrix/projects/fan-controller-v2/web_server.py:156: DeprecationWarning: datetime.datetime.utcnow() is deprecated and scheduled for removal in a future version. Use timezone-aware objects to represent datetimes in UTC: datetime.datetime.now(datetime.UTC). if datetime.utcnow() > expiry: -2026-02-20 15:49:53,771 - fan_controller - INFO - Loaded config from /home/devmatrix/projects/fan-controller-v2/data/config.json -INFO: 192.168.5.30:49451 - "GET /api/status HTTP/1.1" 200 OK -INFO: 192.168.5.30:49451 - "GET /favicon.ico HTTP/1.1" 200 OK -INFO: 192.168.5.30:49451 - "GET /api/status HTTP/1.1" 200 OK -INFO: 192.168.5.30:49451 - "GET /api/status HTTP/1.1" 200 OK -2026-02-20 15:50:02,664 - fan_controller - INFO - Saved config to /home/devmatrix/projects/fan-controller-v2/data/config.json -2026-02-20 15:50:02,666 - fan_controller - ERROR - IPMI command error: [Errno 2] No such file or directory: 'ipmitool' -2026-02-20 15:50:02,666 - fan_controller - ERROR - Failed to connect to IPMI -INFO: 192.168.5.30:49451 - "POST /api/config/ipmi HTTP/1.1" 200 OK +2026-02-20 16:36:09,107 - fan_controller - INFO - Loaded config from /home/devmatrix/projects/fan-controller-v2/data/config.json +INFO: 192.168.5.30:64565 - "GET /api/status HTTP/1.1" 200 OK +INFO: 192.168.5.30:64565 - "GET /favicon.ico HTTP/1.1" 200 OK +INFO: 192.168.5.30:64565 - "GET /api/status HTTP/1.1" 200 OK +INFO: 192.168.5.30:64565 - "GET /api/status HTTP/1.1" 200 OK +2026-02-20 16:36:15,352 - fan_controller - INFO - Saved config to /home/devmatrix/projects/fan-controller-v2/data/config.json +2026-02-20 16:36:15,642 - fan_controller - INFO - Connected to IPMI at 192.168.5.191 +INFO: 192.168.5.30:64565 - "POST /api/config/ipmi HTTP/1.1" 200 OK +INFO: 192.168.5.30:64565 - "GET /favicon.ico HTTP/1.1" 200 OK /home/devmatrix/projects/fan-controller-v2/web_server.py:156: DeprecationWarning: datetime.datetime.utcnow() is deprecated and scheduled for removal in a future version. Use timezone-aware objects to represent datetimes in UTC: datetime.datetime.now(datetime.UTC). if datetime.utcnow() > expiry: -INFO: 192.168.5.30:49451 - "GET /api/status HTTP/1.1" 200 OK -INFO: 192.168.5.30:49451 - "GET /favicon.ico HTTP/1.1" 200 OK -INFO: 192.168.5.30:49451 - "GET /api/status HTTP/1.1" 200 OK -INFO: 192.168.5.30:49451 - "GET /api/status HTTP/1.1" 200 OK -INFO: 192.168.5.30:49451 - "GET /api/status HTTP/1.1" 200 OK -INFO: 192.168.5.30:49451 - "GET /api/status HTTP/1.1" 200 OK -INFO: 127.0.0.1:39328 - "GET /api/status HTTP/1.1" 401 Unauthorized -INFO: 192.168.5.30:49451 - "GET /api/status HTTP/1.1" 200 OK +INFO: 192.168.5.30:64565 - "GET /api/status HTTP/1.1" 200 OK +INFO: 192.168.5.30:64565 - "GET /api/status HTTP/1.1" 200 OK +INFO: 192.168.5.30:64565 - "GET /api/status HTTP/1.1" 200 OK +INFO: 192.168.5.30:64565 - "GET /api/status HTTP/1.1" 200 OK +INFO: 192.168.5.30:64565 - "GET /api/status HTTP/1.1" 200 OK +INFO: 192.168.5.30:64565 - "GET /api/status HTTP/1.1" 200 OK +INFO: 192.168.5.30:64565 - "GET /api/status HTTP/1.1" 200 OK +INFO: 192.168.5.30:64565 - "POST /api/test HTTP/1.1" 200 OK +/home/devmatrix/projects/fan-controller-v2/web_server.py:156: DeprecationWarning: datetime.datetime.utcnow() is deprecated and scheduled for removal in a future version. Use timezone-aware objects to represent datetimes in UTC: datetime.datetime.now(datetime.UTC). + if datetime.utcnow() > expiry: +INFO: 192.168.5.30:64565 - "GET /api/status HTTP/1.1" 200 OK +INFO: 192.168.5.30:64565 - "GET /api/status HTTP/1.1" 200 OK +INFO: 192.168.5.30:64565 - "GET /api/status HTTP/1.1" 200 OK +INFO: 192.168.5.30:64565 - "GET /api/status HTTP/1.1" 200 OK +INFO: 192.168.5.30:64565 - "GET /api/status HTTP/1.1" 200 OK +INFO: 192.168.5.30:64565 - "GET /api/status HTTP/1.1" 200 OK +INFO: 192.168.5.30:64565 - "GET /api/status HTTP/1.1" 200 OK +2026-02-20 16:36:59,135 - fan_controller - INFO - Saved config to /home/devmatrix/projects/fan-controller-v2/data/config.json +2026-02-20 16:36:59,301 - fan_controller - INFO - Fan 0xff speed set to 100% +INFO: 192.168.5.30:64565 - "POST /api/control/manual HTTP/1.1" 200 OK +/home/devmatrix/projects/fan-controller-v2/web_server.py:156: DeprecationWarning: datetime.datetime.utcnow() is deprecated and scheduled for removal in a future version. Use timezone-aware objects to represent datetimes in UTC: datetime.datetime.now(datetime.UTC). + if datetime.utcnow() > expiry: +INFO: 192.168.5.30:64565 - "GET /api/status HTTP/1.1" 200 OK +INFO: 192.168.5.30:64565 - "GET /api/status HTTP/1.1" 200 OK +INFO: 192.168.5.30:64565 - "GET /api/status HTTP/1.1" 200 OK +INFO: 192.168.5.30:64565 - "GET /api/status HTTP/1.1" 200 OK +INFO: 127.0.0.1:42260 - "GET /api/public/temperatures HTTP/1.1" 200 OK +INFO: 192.168.5.30:64565 - "GET /api/status HTTP/1.1" 200 OK +2026-02-20 16:37:10,019 - fan_controller - INFO - Saved config to /home/devmatrix/projects/fan-controller-v2/data/config.json +2026-02-20 16:37:10,171 - fan_controller - INFO - Fan 0xff speed set to 0% +INFO: 192.168.5.30:64565 - "POST /api/control/manual HTTP/1.1" 200 OK +/home/devmatrix/projects/fan-controller-v2/web_server.py:156: DeprecationWarning: datetime.datetime.utcnow() is deprecated and scheduled for removal in a future version. Use timezone-aware objects to represent datetimes in UTC: datetime.datetime.now(datetime.UTC). + if datetime.utcnow() > expiry: +INFO: 192.168.5.30:64565 - "GET /api/status HTTP/1.1" 200 OK +INFO: 192.168.5.30:64565 - "GET /api/status HTTP/1.1" 200 OK +INFO: 192.168.5.30:64565 - "GET /api/status HTTP/1.1" 200 OK +2026-02-20 16:37:16,181 - fan_controller - INFO - Saved config to /home/devmatrix/projects/fan-controller-v2/data/config.json +2026-02-20 16:37:16,392 - fan_controller - INFO - Fan 0xff speed set to 13% +INFO: 192.168.5.30:64565 - "POST /api/control/manual HTTP/1.1" 200 OK +/home/devmatrix/projects/fan-controller-v2/web_server.py:156: DeprecationWarning: datetime.datetime.utcnow() is deprecated and scheduled for removal in a future version. Use timezone-aware objects to represent datetimes in UTC: datetime.datetime.now(datetime.UTC). + if datetime.utcnow() > expiry: +INFO: 192.168.5.30:64565 - "GET /api/status HTTP/1.1" 200 OK +INFO: 192.168.5.30:64565 - "GET /api/status HTTP/1.1" 200 OK /home/devmatrix/projects/fan-controller-v2/web_server.py:149: DeprecationWarning: datetime.datetime.utcnow() is deprecated and scheduled for removal in a future version. Use timezone-aware objects to represent datetimes in UTC: datetime.datetime.now(datetime.UTC). self._sessions[token] = (username, datetime.utcnow() + timedelta(days=7)) -INFO: 127.0.0.1:39340 - "POST /api/auth/login HTTP/1.1" 200 OK -INFO: 192.168.5.30:49451 - "GET /api/status HTTP/1.1" 200 OK -INFO: 192.168.5.30:49451 - "GET /api/status HTTP/1.1" 200 OK -2026-02-20 15:50:24,002 - fan_controller - ERROR - IPMI command error: [Errno 2] No such file or directory: 'ipmitool' -2026-02-20 15:50:24,002 - fan_controller - ERROR - Failed to connect to IPMI -INFO: 192.168.5.30:49451 - "POST /api/test HTTP/1.1" 200 OK +INFO: 127.0.0.1:53160 - "POST /api/auth/login HTTP/1.1" 200 OK +2026-02-20 16:37:20,069 - fan_controller - INFO - Saved config to /home/devmatrix/projects/fan-controller-v2/data/config.json +2026-02-20 16:37:20,231 - fan_controller - INFO - Manual fan control enabled +2026-02-20 16:37:20,400 - fan_controller - INFO - Connected to IPMI at 192.168.5.191 +2026-02-20 16:37:20,400 - fan_controller - INFO - HTTP sensor client initialized for http://192.168.5.200:8888 +2026-02-20 16:37:20,401 - fan_controller - INFO - IPMI Controller service started +INFO: 127.0.0.1:53164 - "POST /api/control/auto HTTP/1.1" 200 OK +2026-02-20 16:37:20,568 - fan_controller - INFO - Manual fan control enabled /home/devmatrix/projects/fan-controller-v2/web_server.py:156: DeprecationWarning: datetime.datetime.utcnow() is deprecated and scheduled for removal in a future version. Use timezone-aware objects to represent datetimes in UTC: datetime.datetime.now(datetime.UTC). if datetime.utcnow() > expiry: -2026-02-20 15:50:25,685 - fan_controller - ERROR - IPMI command error: [Errno 2] No such file or directory: 'ipmitool' -2026-02-20 15:50:25,686 - fan_controller - ERROR - Failed to connect to IPMI -INFO: 127.0.0.1:59364 - "POST /api/test HTTP/1.1" 200 OK +INFO: 192.168.5.30:64565 - "GET /api/status HTTP/1.1" 200 OK /home/devmatrix/projects/fan-controller-v2/web_server.py:156: DeprecationWarning: datetime.datetime.utcnow() is deprecated and scheduled for removal in a future version. Use timezone-aware objects to represent datetimes in UTC: datetime.datetime.now(datetime.UTC). if datetime.utcnow() > expiry: -INFO: 192.168.5.30:49451 - "GET /api/status HTTP/1.1" 200 OK -INFO: 192.168.5.30:49451 - "GET /api/status HTTP/1.1" 200 OK -INFO: 192.168.5.30:49451 - "GET / HTTP/1.1" 200 OK -INFO: 192.168.5.30:49451 - "GET /api/status HTTP/1.1" 200 OK -INFO: 192.168.5.30:49451 - "GET / HTTP/1.1" 200 OK -INFO: 192.168.5.30:49451 - "GET /api/status HTTP/1.1" 200 OK -INFO: 192.168.5.30:49451 - "GET /api/status HTTP/1.1" 200 OK -INFO: 192.168.5.30:49451 - "GET /api/status HTTP/1.1" 200 OK -INFO: 192.168.5.30:49451 - "GET /api/status HTTP/1.1" 200 OK -INFO: 192.168.5.30:49451 - "GET /api/status HTTP/1.1" 200 OK -INFO: 192.168.5.30:49451 - "GET /api/status HTTP/1.1" 200 OK -INFO: 192.168.5.30:49451 - "GET /api/status HTTP/1.1" 200 OK -INFO: 192.168.5.30:49451 - "GET /api/status HTTP/1.1" 200 OK -INFO: 192.168.5.30:49451 - "GET /api/status HTTP/1.1" 200 OK -INFO: 192.168.5.30:49451 - "GET /api/status HTTP/1.1" 200 OK +INFO: 192.168.5.30:64565 - "GET /api/status HTTP/1.1" 200 OK +INFO: 127.0.0.1:54102 - "GET /api/public/temperatures HTTP/1.1" 200 OK +2026-02-20 16:37:26,052 - fan_controller - INFO - Fan 0xff speed set to 15% +2026-02-20 16:37:26,052 - fan_controller - INFO - All fans set to 15% (Temp 27.0°C) +/home/devmatrix/projects/fan-controller-v2/web_server.py:156: DeprecationWarning: datetime.datetime.utcnow() is deprecated and scheduled for removal in a future version. Use timezone-aware objects to represent datetimes in UTC: datetime.datetime.now(datetime.UTC). + if datetime.utcnow() > expiry: +INFO: 192.168.5.30:64565 - "GET /api/status HTTP/1.1" 200 OK +INFO: 192.168.5.30:64565 - "GET /api/status HTTP/1.1" 200 OK +INFO: 192.168.5.30:64565 - "GET /api/status HTTP/1.1" 200 OK +/home/devmatrix/projects/fan-controller-v2/web_server.py:156: DeprecationWarning: datetime.datetime.utcnow() is deprecated and scheduled for removal in a future version. Use timezone-aware objects to represent datetimes in UTC: datetime.datetime.now(datetime.UTC). + if datetime.utcnow() > expiry: +INFO: 192.168.5.30:64565 - "GET /api/status HTTP/1.1" 200 OK +/home/devmatrix/projects/fan-controller-v2/web_server.py:156: DeprecationWarning: datetime.datetime.utcnow() is deprecated and scheduled for removal in a future version. Use timezone-aware objects to represent datetimes in UTC: datetime.datetime.now(datetime.UTC). + if datetime.utcnow() > expiry: +INFO: 192.168.5.30:64565 - "GET /api/status HTTP/1.1" 200 OK +/home/devmatrix/projects/fan-controller-v2/web_server.py:149: DeprecationWarning: datetime.datetime.utcnow() is deprecated and scheduled for removal in a future version. Use timezone-aware objects to represent datetimes in UTC: datetime.datetime.now(datetime.UTC). + self._sessions[token] = (username, datetime.utcnow() + timedelta(days=7)) +INFO: 127.0.0.1:46386 - "POST /api/auth/login HTTP/1.1" 200 OK +INFO: 127.0.0.1:46402 - "GET /api/status HTTP/1.1" 200 OK +INFO: 192.168.5.30:64565 - "GET /api/status HTTP/1.1" 200 OK +INFO: 192.168.5.30:64565 - "GET /api/status HTTP/1.1" 200 OK +INFO: 192.168.5.30:64565 - "GET /api/status HTTP/1.1" 200 OK +INFO: 192.168.5.30:64565 - "GET /api/status HTTP/1.1" 200 OK +INFO: 127.0.0.1:49878 - "POST /api/auth/login HTTP/1.1" 200 OK +/home/devmatrix/projects/fan-controller-v2/web_server.py:156: DeprecationWarning: datetime.datetime.utcnow() is deprecated and scheduled for removal in a future version. Use timezone-aware objects to represent datetimes in UTC: datetime.datetime.now(datetime.UTC). + if datetime.utcnow() > expiry: +2026-02-20 16:37:51,890 - fan_controller - INFO - Saved config to /home/devmatrix/projects/fan-controller-v2/data/config.json +INFO: 127.0.0.1:49884 - "POST /api/config/settings HTTP/1.1" 200 OK +INFO: 192.168.5.30:64565 - "GET /api/status HTTP/1.1" 200 OK +/home/devmatrix/projects/fan-controller-v2/web_server.py:156: DeprecationWarning: datetime.datetime.utcnow() is deprecated and scheduled for removal in a future version. Use timezone-aware objects to represent datetimes in UTC: datetime.datetime.now(datetime.UTC). + if datetime.utcnow() > expiry: +INFO: 192.168.5.30:64565 - "GET /api/status HTTP/1.1" 200 OK +INFO: 127.0.0.1:51568 - "GET /api/status HTTP/1.1" 200 OK +INFO: 192.168.5.30:64565 - "GET /api/status HTTP/1.1" 200 OK +INFO: 192.168.5.30:64565 - "GET /api/status HTTP/1.1" 200 OK +INFO: 192.168.5.30:64565 - "GET /api/status HTTP/1.1" 200 OK +/home/devmatrix/projects/fan-controller-v2/web_server.py:156: DeprecationWarning: datetime.datetime.utcnow() is deprecated and scheduled for removal in a future version. Use timezone-aware objects to represent datetimes in UTC: datetime.datetime.now(datetime.UTC). + if datetime.utcnow() > expiry: +INFO: 192.168.5.30:64565 - "GET /api/status HTTP/1.1" 200 OK +/home/devmatrix/projects/fan-controller-v2/web_server.py:149: DeprecationWarning: datetime.datetime.utcnow() is deprecated and scheduled for removal in a future version. Use timezone-aware objects to represent datetimes in UTC: datetime.datetime.now(datetime.UTC). + self._sessions[token] = (username, datetime.utcnow() + timedelta(days=7)) +INFO: 127.0.0.1:60806 - "POST /api/auth/login HTTP/1.1" 200 OK +/home/devmatrix/projects/fan-controller-v2/web_server.py:156: DeprecationWarning: datetime.datetime.utcnow() is deprecated and scheduled for removal in a future version. Use timezone-aware objects to represent datetimes in UTC: datetime.datetime.now(datetime.UTC). + if datetime.utcnow() > expiry: +2026-02-20 16:38:11,328 - fan_controller - INFO - Saved config to /home/devmatrix/projects/fan-controller-v2/data/config.json +INFO: 127.0.0.1:60810 - "POST /api/config/settings HTTP/1.1" 200 OK +INFO: 192.168.5.30:64565 - "GET /api/status HTTP/1.1" 200 OK +2026-02-20 16:38:12,401 - fan_controller - INFO - Fan 0xff speed set to 44% +2026-02-20 16:38:12,401 - fan_controller - INFO - All fans set to 44% (Temp 52.0°C) +/home/devmatrix/projects/fan-controller-v2/web_server.py:156: DeprecationWarning: datetime.datetime.utcnow() is deprecated and scheduled for removal in a future version. Use timezone-aware objects to represent datetimes in UTC: datetime.datetime.now(datetime.UTC). + if datetime.utcnow() > expiry: +INFO: 192.168.5.30:64565 - "GET /api/status HTTP/1.1" 200 OK +INFO: 127.0.0.1:40062 - "GET /api/status HTTP/1.1" 200 OK +INFO: 192.168.5.30:64565 - "GET /api/status HTTP/1.1" 200 OK +INFO: 192.168.5.30:53448 - "GET /api/status HTTP/1.1" 200 OK +/home/devmatrix/projects/fan-controller-v2/web_server.py:156: DeprecationWarning: datetime.datetime.utcnow() is deprecated and scheduled for removal in a future version. Use timezone-aware objects to represent datetimes in UTC: datetime.datetime.now(datetime.UTC). + if datetime.utcnow() > expiry: +INFO: 192.168.5.30:53448 - "GET /api/status HTTP/1.1" 200 OK +INFO: 192.168.5.30:53448 - "GET /api/status HTTP/1.1" 200 OK +/home/devmatrix/projects/fan-controller-v2/web_server.py:149: DeprecationWarning: datetime.datetime.utcnow() is deprecated and scheduled for removal in a future version. Use timezone-aware objects to represent datetimes in UTC: datetime.datetime.now(datetime.UTC). + self._sessions[token] = (username, datetime.utcnow() + timedelta(days=7)) +INFO: 127.0.0.1:34550 - "POST /api/auth/login HTTP/1.1" 200 OK +2026-02-20 16:38:28,624 - fan_controller - INFO - Saved config to /home/devmatrix/projects/fan-controller-v2/data/config.json +INFO: 127.0.0.1:34556 - "POST /api/config/settings HTTP/1.1" 200 OK +INFO: 192.168.5.30:53448 - "GET /api/status HTTP/1.1" 200 OK +INFO: 192.168.5.30:53448 - "GET /api/status HTTP/1.1" 200 OK diff --git a/setup-sensors-server.sh b/setup-sensors-server.sh new file mode 100644 index 0000000..33fd410 --- /dev/null +++ b/setup-sensors-server.sh @@ -0,0 +1,117 @@ +#!/bin/bash +# IPMI Controller - lm-sensors HTTP Server Setup +# Run this on your Proxmox/Dell server to expose sensors over HTTP + +set -e + +echo "🌡️ IPMI Controller - lm-sensors HTTP Setup" +echo "============================================" + +# Check if running as root +if [ "$EUID" -ne 0 ]; then + echo "❌ Please run as root (sudo)" + exit 1 +fi + +# Install lm-sensors if not present +echo "" +echo "📦 Checking lm-sensors..." +if ! command -v sensors &> /dev/null; then + echo "Installing lm-sensors..." + apt-get update + apt-get install -y lm-sensors + + echo "" + echo "🔧 Running sensors-detect..." + echo "Answer YES to all questions or use default values" + sensors-detect --auto +else + echo "✓ lm-sensors already installed" +fi + +# Install netcat if not present +if ! command -v nc &> /dev/null; then + echo "Installing netcat..." + apt-get install -y netcat-openbsd +fi + +# Create the HTTP sensors server script +SERVER_SCRIPT="/usr/local/bin/sensors-http-server.sh" + +echo "" +echo "📝 Creating HTTP server script..." +cat > "$SERVER_SCRIPT" << 'EOF' +#!/bin/bash +# lm-sensors HTTP Server for IPMI Controller +# Serves sensor data on port 8888 + +PORT=${1:-8888} + +echo "Starting lm-sensors HTTP server on port $PORT..." +echo "Access via: http://$(hostname -I | awk '{print $1}'):$PORT" + +while true; do + { + echo -e "HTTP/1.1 200 OK\r" + echo -e "Content-Type: text/plain\r" + echo -e "Access-Control-Allow-Origin: *\r" + echo -e "\r" + sensors -u 2>/dev/null || echo "Error reading sensors" + } | nc -l -p "$PORT" -q 1 +done +EOF + +chmod +x "$SERVER_SCRIPT" +echo "✓ Created $SERVER_SCRIPT" + +# Create systemd service +SERVICE_FILE="/etc/systemd/system/sensors-http.service" + +echo "" +echo "🔧 Creating systemd service..." +cat > "$SERVICE_FILE" << EOF +[Unit] +Description=lm-sensors HTTP Server for IPMI Controller +After=network.target + +[Service] +Type=simple +ExecStart=$SERVER_SCRIPT 8888 +Restart=always +RestartSec=5 +User=root + +[Install] +WantedBy=multi-user.target +EOF + +echo "✓ Created $SERVICE_FILE" + +# Reload systemd and enable service +echo "" +echo "🚀 Enabling and starting service..." +systemctl daemon-reload +systemctl enable sensors-http.service +systemctl start sensors-http.service + +# Check status +sleep 2 +if systemctl is-active --quiet sensors-http.service; then + echo "✓ Service is running!" + echo "" + echo "🌐 HTTP Endpoint: http://$(hostname -I | awk '{print $1}'):8888" + echo "" + echo "Test with: curl http://$(hostname -I | awk '{print $1}'):8888" +else + echo "⚠️ Service failed to start. Check logs:" + echo " journalctl -u sensors-http.service -f" +fi + +echo "" +echo "📋 Management Commands:" +echo " Start: sudo systemctl start sensors-http" +echo " Stop: sudo systemctl stop sensors-http" +echo " Status: sudo systemctl status sensors-http" +echo " Logs: sudo journalctl -u sensors-http -f" +echo "" +echo "✅ Setup complete!" diff --git a/web_server.py b/web_server.py index f70a6b3..6355981 100644 --- a/web_server.py +++ b/web_server.py @@ -751,6 +751,13 @@ def get_html(theme="dark"): const avgSpeed = currentStatus.current_speeds?.all || 0; document.getElementById('val-fans').textContent = avgSpeed + '%'; + // Sync slider with current speed (only if not currently dragging) + const slider = document.getElementById('manual-speed'); + if (slider && document.activeElement !== slider) {{ + slider.value = avgSpeed; + document.getElementById('manual-val').textContent = avgSpeed + '%'; + }} + document.getElementById('val-sensors').textContent = temps.length; // Temperature grid