From 25d24f07de1d1fb0ab44f8481d6e355a2adf02ba Mon Sep 17 00:00:00 2001 From: devmatrix Date: Fri, 20 Feb 2026 22:48:01 +0000 Subject: [PATCH] Improve temperature sensor display with grouped categories --- fan_controller.py | 16 +- server.log | 378 +++++++++++++++++++++++++++++++++++++++++++--- web_server.py | 113 ++++++++++++-- 3 files changed, 469 insertions(+), 38 deletions(-) diff --git a/fan_controller.py b/fan_controller.py index cf83b1f..0f68276 100644 --- a/fan_controller.py +++ b/fan_controller.py @@ -113,7 +113,7 @@ class HTTPSensorClient: return temps def _classify_sensor_name(self, name: str, chip: str) -> str: - """Classify sensor location from name.""" + """Classify sensor location from name with detailed categories.""" import re name_lower = name.lower() chip_lower = chip.lower() @@ -139,9 +139,19 @@ class HTTPSensorClient: return "cpu" elif "tdie" in name_lower or "tctl" in name_lower: return "cpu" - elif "pcie" in name_lower or "nvme" in name_lower or "composite" in name_lower: + elif "nvme" in name_lower or "composite" in name_lower: + return "nvme" + elif "raid" in name_lower or "megaraid" in name_lower: + return "raid" + elif "pcie" in name_lower: return "pcie" - elif "loc1" in name_lower or "loc2" in name_lower: + elif "inlet" in name_lower or "ambient" in name_lower or "room" in name_lower: + return "ambient" + elif "exhaust" in name_lower or "outlet" in name_lower: + return "exhaust" + elif "inlet" in name_lower: + return "inlet" + elif "loc1" in name_lower or "loc2" in name_lower or "chipset" in name_lower: return "chipset" return "other" diff --git a/server.log b/server.log index 000bc11..c161183 100644 --- a/server.log +++ b/server.log @@ -1,21 +1,16 @@ -INFO: Started server process [103738] +INFO: Started server process [105401] INFO: Waiting for application startup. -2026-02-20 22:29:23,172 - fan_controller - INFO - Loaded config from /home/devmatrix/projects/fan-controller-v2/data/config.json -2026-02-20 22:29:23,173 - __main__ - INFO - Auto-starting fan control (enabled in config) -2026-02-20 22:29:23,328 - fan_controller - INFO - Connected to IPMI at 192.168.5.191 -2026-02-20 22:29:23,329 - fan_controller - INFO - HTTP sensor client initialized for http://192.168.5.200:8888 -2026-02-20 22:29:23,330 - fan_controller - INFO - IPMI Controller service started +2026-02-20 22:36:05,954 - fan_controller - INFO - Loaded config from /home/devmatrix/projects/fan-controller-v2/data/config.json +2026-02-20 22:36:05,955 - __main__ - INFO - Auto-starting fan control (enabled in config) +2026-02-20 22:36:06,109 - fan_controller - INFO - Connected to IPMI at 192.168.5.191 +2026-02-20 22:36:06,110 - fan_controller - INFO - HTTP sensor client initialized for http://192.168.5.200:8888 +2026-02-20 22:36:06,111 - fan_controller - INFO - IPMI Controller service started INFO: Application startup complete. INFO: Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to quit) -2026-02-20 22:29:23,495 - fan_controller - INFO - Manual fan control enabled -INFO: 192.168.5.30:54938 - "GET /api/status HTTP/1.1" 401 Unauthorized -INFO: 192.168.5.30:54938 - "GET /login HTTP/1.1" 200 OK -2026-02-20 22:29:29,168 - fan_controller - INFO - Fan 0xff speed set to 14% -2026-02-20 22:29:29,168 - fan_controller - INFO - All fans set to 14% (Temp 38.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). - self._sessions[token] = (username, datetime.utcnow() + timedelta(days=7)) -INFO: 192.168.5.30:50571 - "POST /api/auth/login HTTP/1.1" 200 OK -INFO: 192.168.5.30:50571 - "GET / HTTP/1.1" 500 Internal Server Error +2026-02-20 22:36:06,301 - fan_controller - INFO - Manual fan control enabled +2026-02-20 22:36:11,732 - fan_controller - INFO - Fan 0xff speed set to 14% +2026-02-20 22:36:11,732 - fan_controller - INFO - All fans set to 14% (Temp 38.0°C) +INFO: 192.168.5.30:57657 - "GET / HTTP/1.1" 500 Internal Server Error ERROR: Exception in ASGI application Traceback (most recent call last): File "/home/devmatrix/.local/lib/python3.12/site-packages/uvicorn/protocols/http/httptools_impl.py", line 419, in run_asgi @@ -70,13 +65,8 @@ Traceback (most recent call last): ^^^^^^^ NameError: name 'padding' is not defined -INFO: 192.168.5.30:64908 - "GET /http%3A//192.168.5.210%3A3000/favicon.ico HTTP/1.1" 404 Not Found -INFO: 192.168.5.30:64908 - "GET /login HTTP/1.1" 200 OK -INFO: 192.168.5.30:64908 - "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). - self._sessions[token] = (username, datetime.utcnow() + timedelta(days=7)) -INFO: 192.168.5.30:52032 - "POST /api/auth/login HTTP/1.1" 200 OK -INFO: 192.168.5.30:52032 - "GET / HTTP/1.1" 500 Internal Server Error +INFO: 192.168.5.30:65161 - "GET /favicon.ico HTTP/1.1" 200 OK +INFO: 192.168.5.30:65161 - "GET / HTTP/1.1" 500 Internal Server Error ERROR: Exception in ASGI application Traceback (most recent call last): File "/home/devmatrix/.local/lib/python3.12/site-packages/uvicorn/protocols/http/httptools_impl.py", line 419, in run_asgi @@ -131,4 +121,346 @@ Traceback (most recent call last): ^^^^^^^ NameError: name 'padding' is not defined -INFO: 192.168.5.30:51945 - "GET /http%3A//192.168.5.210%3A3000/favicon.ico HTTP/1.1" 404 Not Found +INFO: 192.168.5.30:51526 - "GET /favicon.ico HTTP/1.1" 200 OK +INFO: 192.168.5.30:53588 - "GET / HTTP/1.1" 500 Internal Server Error +ERROR: Exception in ASGI application +Traceback (most recent call last): + File "/home/devmatrix/.local/lib/python3.12/site-packages/uvicorn/protocols/http/httptools_impl.py", line 419, in run_asgi + result = await app( # type: ignore[func-returns-value] + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/devmatrix/.local/lib/python3.12/site-packages/uvicorn/middleware/proxy_headers.py", line 84, in __call__ + return await self.app(scope, receive, send) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/devmatrix/.local/lib/python3.12/site-packages/fastapi/applications.py", line 1054, in __call__ + await super().__call__(scope, receive, send) + File "/home/devmatrix/.local/lib/python3.12/site-packages/starlette/applications.py", line 123, in __call__ + await self.middleware_stack(scope, receive, send) + File "/home/devmatrix/.local/lib/python3.12/site-packages/starlette/middleware/errors.py", line 186, in __call__ + raise exc + File "/home/devmatrix/.local/lib/python3.12/site-packages/starlette/middleware/errors.py", line 164, in __call__ + await self.app(scope, receive, _send) + File "/home/devmatrix/.local/lib/python3.12/site-packages/starlette/middleware/cors.py", line 83, in __call__ + await self.app(scope, receive, send) + File "/home/devmatrix/.local/lib/python3.12/site-packages/starlette/middleware/exceptions.py", line 62, in __call__ + await wrap_app_handling_exceptions(self.app, conn)(scope, receive, send) + File "/home/devmatrix/.local/lib/python3.12/site-packages/starlette/_exception_handler.py", line 64, in wrapped_app + raise exc + File "/home/devmatrix/.local/lib/python3.12/site-packages/starlette/_exception_handler.py", line 53, in wrapped_app + await app(scope, receive, sender) + File "/home/devmatrix/.local/lib/python3.12/site-packages/starlette/routing.py", line 762, in __call__ + await self.middleware_stack(scope, receive, send) + File "/home/devmatrix/.local/lib/python3.12/site-packages/starlette/routing.py", line 782, in app + await route.handle(scope, receive, send) + File "/home/devmatrix/.local/lib/python3.12/site-packages/starlette/routing.py", line 297, in handle + await self.app(scope, receive, send) + File "/home/devmatrix/.local/lib/python3.12/site-packages/starlette/routing.py", line 77, in app + await wrap_app_handling_exceptions(app, request)(scope, receive, send) + File "/home/devmatrix/.local/lib/python3.12/site-packages/starlette/_exception_handler.py", line 64, in wrapped_app + raise exc + File "/home/devmatrix/.local/lib/python3.12/site-packages/starlette/_exception_handler.py", line 53, in wrapped_app + await app(scope, receive, sender) + File "/home/devmatrix/.local/lib/python3.12/site-packages/starlette/routing.py", line 72, in app + response = await func(request) + ^^^^^^^^^^^^^^^^^^^ + File "/home/devmatrix/.local/lib/python3.12/site-packages/fastapi/routing.py", line 299, in app + raise e + File "/home/devmatrix/.local/lib/python3.12/site-packages/fastapi/routing.py", line 294, in app + raw_response = await run_endpoint_function( + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/devmatrix/.local/lib/python3.12/site-packages/fastapi/routing.py", line 191, in run_endpoint_function + return await dependant.call(**values) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/devmatrix/projects/fan-controller-v2/web_server.py", line 1592, in root + return HTMLResponse(content=get_html(theme)) + ^^^^^^^^^^^^^^^ + File "/home/devmatrix/projects/fan-controller-v2/web_server.py", line 1424, in get_html + + ^^^^^^^ +NameError: name 'padding' is not defined +INFO: 192.168.5.30:58112 - "GET /favicon.ico HTTP/1.1" 200 OK +INFO: 192.168.5.30:61736 - "GET / HTTP/1.1" 500 Internal Server Error +ERROR: Exception in ASGI application +Traceback (most recent call last): + File "/home/devmatrix/.local/lib/python3.12/site-packages/uvicorn/protocols/http/httptools_impl.py", line 419, in run_asgi + result = await app( # type: ignore[func-returns-value] + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/devmatrix/.local/lib/python3.12/site-packages/uvicorn/middleware/proxy_headers.py", line 84, in __call__ + return await self.app(scope, receive, send) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/devmatrix/.local/lib/python3.12/site-packages/fastapi/applications.py", line 1054, in __call__ + await super().__call__(scope, receive, send) + File "/home/devmatrix/.local/lib/python3.12/site-packages/starlette/applications.py", line 123, in __call__ + await self.middleware_stack(scope, receive, send) + File "/home/devmatrix/.local/lib/python3.12/site-packages/starlette/middleware/errors.py", line 186, in __call__ + raise exc + File "/home/devmatrix/.local/lib/python3.12/site-packages/starlette/middleware/errors.py", line 164, in __call__ + await self.app(scope, receive, _send) + File "/home/devmatrix/.local/lib/python3.12/site-packages/starlette/middleware/cors.py", line 83, in __call__ + await self.app(scope, receive, send) + File "/home/devmatrix/.local/lib/python3.12/site-packages/starlette/middleware/exceptions.py", line 62, in __call__ + await wrap_app_handling_exceptions(self.app, conn)(scope, receive, send) + File "/home/devmatrix/.local/lib/python3.12/site-packages/starlette/_exception_handler.py", line 64, in wrapped_app + raise exc + File "/home/devmatrix/.local/lib/python3.12/site-packages/starlette/_exception_handler.py", line 53, in wrapped_app + await app(scope, receive, sender) + File "/home/devmatrix/.local/lib/python3.12/site-packages/starlette/routing.py", line 762, in __call__ + await self.middleware_stack(scope, receive, send) + File "/home/devmatrix/.local/lib/python3.12/site-packages/starlette/routing.py", line 782, in app + await route.handle(scope, receive, send) + File "/home/devmatrix/.local/lib/python3.12/site-packages/starlette/routing.py", line 297, in handle + await self.app(scope, receive, send) + File "/home/devmatrix/.local/lib/python3.12/site-packages/starlette/routing.py", line 77, in app + await wrap_app_handling_exceptions(app, request)(scope, receive, send) + File "/home/devmatrix/.local/lib/python3.12/site-packages/starlette/_exception_handler.py", line 64, in wrapped_app + raise exc + File "/home/devmatrix/.local/lib/python3.12/site-packages/starlette/_exception_handler.py", line 53, in wrapped_app + await app(scope, receive, sender) + File "/home/devmatrix/.local/lib/python3.12/site-packages/starlette/routing.py", line 72, in app + response = await func(request) + ^^^^^^^^^^^^^^^^^^^ + File "/home/devmatrix/.local/lib/python3.12/site-packages/fastapi/routing.py", line 299, in app + raise e + File "/home/devmatrix/.local/lib/python3.12/site-packages/fastapi/routing.py", line 294, in app + raw_response = await run_endpoint_function( + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/devmatrix/.local/lib/python3.12/site-packages/fastapi/routing.py", line 191, in run_endpoint_function + return await dependant.call(**values) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/devmatrix/projects/fan-controller-v2/web_server.py", line 1592, in root + if not user_manager.is_setup_complete(): + ^^^^^^^^^^^^^ + File "/home/devmatrix/projects/fan-controller-v2/web_server.py", line 1424, in get_html + 📁 GitHub Repo + ^^^^^^^ +NameError: name 'padding' is not defined +INFO: 192.168.5.30:64381 - "GET /favicon.ico HTTP/1.1" 200 OK +INFO: 192.168.5.30:64381 - "GET / HTTP/1.1" 500 Internal Server Error +ERROR: Exception in ASGI application +Traceback (most recent call last): + File "/home/devmatrix/.local/lib/python3.12/site-packages/uvicorn/protocols/http/httptools_impl.py", line 419, in run_asgi + result = await app( # type: ignore[func-returns-value] + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/devmatrix/.local/lib/python3.12/site-packages/uvicorn/middleware/proxy_headers.py", line 84, in __call__ + return await self.app(scope, receive, send) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/devmatrix/.local/lib/python3.12/site-packages/fastapi/applications.py", line 1054, in __call__ + await super().__call__(scope, receive, send) + File "/home/devmatrix/.local/lib/python3.12/site-packages/starlette/applications.py", line 123, in __call__ + await self.middleware_stack(scope, receive, send) + File "/home/devmatrix/.local/lib/python3.12/site-packages/starlette/middleware/errors.py", line 186, in __call__ + raise exc + File "/home/devmatrix/.local/lib/python3.12/site-packages/starlette/middleware/errors.py", line 164, in __call__ + await self.app(scope, receive, _send) + File "/home/devmatrix/.local/lib/python3.12/site-packages/starlette/middleware/cors.py", line 83, in __call__ + await self.app(scope, receive, send) + File "/home/devmatrix/.local/lib/python3.12/site-packages/starlette/middleware/exceptions.py", line 62, in __call__ + await wrap_app_handling_exceptions(self.app, conn)(scope, receive, send) + File "/home/devmatrix/.local/lib/python3.12/site-packages/starlette/_exception_handler.py", line 64, in wrapped_app + raise exc + File "/home/devmatrix/.local/lib/python3.12/site-packages/starlette/_exception_handler.py", line 53, in wrapped_app + await app(scope, receive, sender) + File "/home/devmatrix/.local/lib/python3.12/site-packages/starlette/routing.py", line 762, in __call__ + await self.middleware_stack(scope, receive, send) + File "/home/devmatrix/.local/lib/python3.12/site-packages/starlette/routing.py", line 782, in app + await route.handle(scope, receive, send) + File "/home/devmatrix/.local/lib/python3.12/site-packages/starlette/routing.py", line 297, in handle + await self.app(scope, receive, send) + File "/home/devmatrix/.local/lib/python3.12/site-packages/starlette/routing.py", line 77, in app + await wrap_app_handling_exceptions(app, request)(scope, receive, send) + File "/home/devmatrix/.local/lib/python3.12/site-packages/starlette/_exception_handler.py", line 64, in wrapped_app + raise exc + File "/home/devmatrix/.local/lib/python3.12/site-packages/starlette/_exception_handler.py", line 53, in wrapped_app + await app(scope, receive, sender) + File "/home/devmatrix/.local/lib/python3.12/site-packages/starlette/routing.py", line 72, in app + response = await func(request) + ^^^^^^^^^^^^^^^^^^^ + File "/home/devmatrix/.local/lib/python3.12/site-packages/fastapi/routing.py", line 299, in app + raise e + File "/home/devmatrix/.local/lib/python3.12/site-packages/fastapi/routing.py", line 294, in app + raw_response = await run_endpoint_function( + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/devmatrix/.local/lib/python3.12/site-packages/fastapi/routing.py", line 191, in run_endpoint_function + return await dependant.call(**values) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/devmatrix/projects/fan-controller-v2/web_server.py", line 1592, in root + if not user_manager.is_setup_complete(): + ^^^^^^^^^^^^^ + File "/home/devmatrix/projects/fan-controller-v2/web_server.py", line 1424, in get_html + 📁 GitHub Repo + ^^^^^^^ +NameError: name 'padding' is not defined +INFO: 192.168.5.30:59631 - "GET / HTTP/1.1" 500 Internal Server Error +ERROR: Exception in ASGI application +Traceback (most recent call last): + File "/home/devmatrix/.local/lib/python3.12/site-packages/uvicorn/protocols/http/httptools_impl.py", line 419, in run_asgi + result = await app( # type: ignore[func-returns-value] + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/devmatrix/.local/lib/python3.12/site-packages/uvicorn/middleware/proxy_headers.py", line 84, in __call__ + return await self.app(scope, receive, send) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/devmatrix/.local/lib/python3.12/site-packages/fastapi/applications.py", line 1054, in __call__ + await super().__call__(scope, receive, send) + File "/home/devmatrix/.local/lib/python3.12/site-packages/starlette/applications.py", line 123, in __call__ + await self.middleware_stack(scope, receive, send) + File "/home/devmatrix/.local/lib/python3.12/site-packages/starlette/middleware/errors.py", line 186, in __call__ + raise exc + File "/home/devmatrix/.local/lib/python3.12/site-packages/starlette/middleware/errors.py", line 164, in __call__ + await self.app(scope, receive, _send) + File "/home/devmatrix/.local/lib/python3.12/site-packages/starlette/middleware/cors.py", line 83, in __call__ + await self.app(scope, receive, send) + File "/home/devmatrix/.local/lib/python3.12/site-packages/starlette/middleware/exceptions.py", line 62, in __call__ + await wrap_app_handling_exceptions(self.app, conn)(scope, receive, send) + File "/home/devmatrix/.local/lib/python3.12/site-packages/starlette/_exception_handler.py", line 64, in wrapped_app + raise exc + File "/home/devmatrix/.local/lib/python3.12/site-packages/starlette/_exception_handler.py", line 53, in wrapped_app + await app(scope, receive, sender) + File "/home/devmatrix/.local/lib/python3.12/site-packages/starlette/routing.py", line 762, in __call__ + await self.middleware_stack(scope, receive, send) + File "/home/devmatrix/.local/lib/python3.12/site-packages/starlette/routing.py", line 782, in app + await route.handle(scope, receive, send) + File "/home/devmatrix/.local/lib/python3.12/site-packages/starlette/routing.py", line 297, in handle + await self.app(scope, receive, send) + File "/home/devmatrix/.local/lib/python3.12/site-packages/starlette/routing.py", line 77, in app + await wrap_app_handling_exceptions(app, request)(scope, receive, send) + File "/home/devmatrix/.local/lib/python3.12/site-packages/starlette/_exception_handler.py", line 64, in wrapped_app + raise exc + File "/home/devmatrix/.local/lib/python3.12/site-packages/starlette/_exception_handler.py", line 53, in wrapped_app + await app(scope, receive, sender) + File "/home/devmatrix/.local/lib/python3.12/site-packages/starlette/routing.py", line 72, in app + response = await func(request) + ^^^^^^^^^^^^^^^^^^^ + File "/home/devmatrix/.local/lib/python3.12/site-packages/fastapi/routing.py", line 299, in app + raise e + File "/home/devmatrix/.local/lib/python3.12/site-packages/fastapi/routing.py", line 294, in app + raw_response = await run_endpoint_function( + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/devmatrix/.local/lib/python3.12/site-packages/fastapi/routing.py", line 191, in run_endpoint_function + return await dependant.call(**values) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/devmatrix/projects/fan-controller-v2/web_server.py", line 1592, in root + if not user_manager.is_setup_complete(): + ^^^^^^^^^^^^^ + File "/home/devmatrix/projects/fan-controller-v2/web_server.py", line 1424, in get_html + 📁 GitHub Repo + ^^^^^^^ +NameError: name 'padding' is not defined +INFO: 192.168.5.30:56967 - "GET /favicon.ico HTTP/1.1" 200 OK +INFO: 192.168.5.30:56967 - "GET / HTTP/1.1" 500 Internal Server Error +ERROR: Exception in ASGI application +Traceback (most recent call last): + File "/home/devmatrix/.local/lib/python3.12/site-packages/uvicorn/protocols/http/httptools_impl.py", line 419, in run_asgi + result = await app( # type: ignore[func-returns-value] + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/devmatrix/.local/lib/python3.12/site-packages/uvicorn/middleware/proxy_headers.py", line 84, in __call__ + return await self.app(scope, receive, send) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/devmatrix/.local/lib/python3.12/site-packages/fastapi/applications.py", line 1054, in __call__ + await super().__call__(scope, receive, send) + File "/home/devmatrix/.local/lib/python3.12/site-packages/starlette/applications.py", line 123, in __call__ + await self.middleware_stack(scope, receive, send) + File "/home/devmatrix/.local/lib/python3.12/site-packages/starlette/middleware/errors.py", line 186, in __call__ + raise exc + File "/home/devmatrix/.local/lib/python3.12/site-packages/starlette/middleware/errors.py", line 164, in __call__ + await self.app(scope, receive, _send) + File "/home/devmatrix/.local/lib/python3.12/site-packages/starlette/middleware/cors.py", line 83, in __call__ + await self.app(scope, receive, send) + File "/home/devmatrix/.local/lib/python3.12/site-packages/starlette/middleware/exceptions.py", line 62, in __call__ + await wrap_app_handling_exceptions(self.app, conn)(scope, receive, send) + File "/home/devmatrix/.local/lib/python3.12/site-packages/starlette/_exception_handler.py", line 64, in wrapped_app + raise exc + File "/home/devmatrix/.local/lib/python3.12/site-packages/starlette/_exception_handler.py", line 53, in wrapped_app + await app(scope, receive, sender) + File "/home/devmatrix/.local/lib/python3.12/site-packages/starlette/routing.py", line 762, in __call__ + await self.middleware_stack(scope, receive, send) + File "/home/devmatrix/.local/lib/python3.12/site-packages/starlette/routing.py", line 782, in app + await route.handle(scope, receive, send) + File "/home/devmatrix/.local/lib/python3.12/site-packages/starlette/routing.py", line 297, in handle + await self.app(scope, receive, send) + File "/home/devmatrix/.local/lib/python3.12/site-packages/starlette/routing.py", line 77, in app + await wrap_app_handling_exceptions(app, request)(scope, receive, send) + File "/home/devmatrix/.local/lib/python3.12/site-packages/starlette/_exception_handler.py", line 64, in wrapped_app + raise exc + File "/home/devmatrix/.local/lib/python3.12/site-packages/starlette/_exception_handler.py", line 53, in wrapped_app + await app(scope, receive, sender) + File "/home/devmatrix/.local/lib/python3.12/site-packages/starlette/routing.py", line 72, in app + response = await func(request) + ^^^^^^^^^^^^^^^^^^^ + File "/home/devmatrix/.local/lib/python3.12/site-packages/fastapi/routing.py", line 299, in app + raise e + File "/home/devmatrix/.local/lib/python3.12/site-packages/fastapi/routing.py", line 294, in app + raw_response = await run_endpoint_function( + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/devmatrix/.local/lib/python3.12/site-packages/fastapi/routing.py", line 191, in run_endpoint_function + return await dependant.call(**values) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/devmatrix/projects/fan-controller-v2/web_server.py", line 1592, in root + if not user_manager.is_setup_complete(): + ^^^^^^^^^^^^^ + File "/home/devmatrix/projects/fan-controller-v2/web_server.py", line 1424, in get_html + 📁 GitHub Repo + ^^^^^^^ +NameError: name 'padding' is not defined +INFO: 192.168.5.30:51136 - "GET /favicon.ico HTTP/1.1" 200 OK +INFO: 192.168.5.30:51136 - "GET / HTTP/1.1" 500 Internal Server Error +ERROR: Exception in ASGI application +Traceback (most recent call last): + File "/home/devmatrix/.local/lib/python3.12/site-packages/uvicorn/protocols/http/httptools_impl.py", line 419, in run_asgi + result = await app( # type: ignore[func-returns-value] + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/devmatrix/.local/lib/python3.12/site-packages/uvicorn/middleware/proxy_headers.py", line 84, in __call__ + return await self.app(scope, receive, send) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/devmatrix/.local/lib/python3.12/site-packages/fastapi/applications.py", line 1054, in __call__ + await super().__call__(scope, receive, send) + File "/home/devmatrix/.local/lib/python3.12/site-packages/starlette/applications.py", line 123, in __call__ + await self.middleware_stack(scope, receive, send) + File "/home/devmatrix/.local/lib/python3.12/site-packages/starlette/middleware/errors.py", line 186, in __call__ + raise exc + File "/home/devmatrix/.local/lib/python3.12/site-packages/starlette/middleware/errors.py", line 164, in __call__ + await self.app(scope, receive, _send) + File "/home/devmatrix/.local/lib/python3.12/site-packages/starlette/middleware/cors.py", line 83, in __call__ + await self.app(scope, receive, send) + File "/home/devmatrix/.local/lib/python3.12/site-packages/starlette/middleware/exceptions.py", line 62, in __call__ + await wrap_app_handling_exceptions(self.app, conn)(scope, receive, send) + File "/home/devmatrix/.local/lib/python3.12/site-packages/starlette/_exception_handler.py", line 64, in wrapped_app + raise exc + File "/home/devmatrix/.local/lib/python3.12/site-packages/starlette/_exception_handler.py", line 53, in wrapped_app + await app(scope, receive, sender) + File "/home/devmatrix/.local/lib/python3.12/site-packages/starlette/routing.py", line 762, in __call__ + await self.middleware_stack(scope, receive, send) + File "/home/devmatrix/.local/lib/python3.12/site-packages/starlette/routing.py", line 782, in app + await route.handle(scope, receive, send) + File "/home/devmatrix/.local/lib/python3.12/site-packages/starlette/routing.py", line 297, in handle + await self.app(scope, receive, send) + File "/home/devmatrix/.local/lib/python3.12/site-packages/starlette/routing.py", line 77, in app + await wrap_app_handling_exceptions(app, request)(scope, receive, send) + File "/home/devmatrix/.local/lib/python3.12/site-packages/starlette/_exception_handler.py", line 64, in wrapped_app + raise exc + File "/home/devmatrix/.local/lib/python3.12/site-packages/starlette/_exception_handler.py", line 53, in wrapped_app + await app(scope, receive, sender) + File "/home/devmatrix/.local/lib/python3.12/site-packages/starlette/routing.py", line 72, in app + response = await func(request) + ^^^^^^^^^^^^^^^^^^^ + File "/home/devmatrix/.local/lib/python3.12/site-packages/fastapi/routing.py", line 299, in app + raise e + File "/home/devmatrix/.local/lib/python3.12/site-packages/fastapi/routing.py", line 294, in app + raw_response = await run_endpoint_function( + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/devmatrix/.local/lib/python3.12/site-packages/fastapi/routing.py", line 191, in run_endpoint_function + return await dependant.call(**values) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/devmatrix/projects/fan-controller-v2/web_server.py", line 1592, in root + if not user_manager.is_setup_complete(): + ^^^^^^^^^^^^^ + File "/home/devmatrix/projects/fan-controller-v2/web_server.py", line 1424, in get_html + 📁 GitHub Repo + ^^^^^^^ +NameError: name 'padding' is not defined +2026-02-20 22:45:21,250 - fan_controller - INFO - Fan 0xff speed set to 15% +2026-02-20 22:45:21,250 - fan_controller - INFO - All fans set to 15% (Temp 40.0°C) +2026-02-20 22:45:36,965 - fan_controller - INFO - Fan 0xff speed set to 14% +2026-02-20 22:45:36,965 - fan_controller - INFO - All fans set to 14% (Temp 39.0°C) +2026-02-20 22:46:56,801 - fan_controller - INFO - Fan 0xff speed set to 15% +2026-02-20 22:46:56,801 - fan_controller - INFO - All fans set to 15% (Temp 40.0°C) +2026-02-20 22:47:12,899 - fan_controller - INFO - Fan 0xff speed set to 14% +2026-02-20 22:47:12,900 - fan_controller - INFO - All fans set to 14% (Temp 38.0°C) diff --git a/web_server.py b/web_server.py index f1c74c4..282c7ee 100644 --- a/web_server.py +++ b/web_server.py @@ -541,8 +541,13 @@ def get_html(theme="dark"):

Temperatures

-
-
Loading...
+
+
+
+
+
+
+
@@ -858,17 +863,101 @@ def get_html(theme="dark"): document.getElementById('val-sensors').textContent = temps.length; - // Temperature grid - const tempGrid = document.getElementById('temp-grid'); - if (temps.length > 0) {{ - tempGrid.innerHTML = temps.map(t => {{ + // Temperature display - grouped by category + const temps = currentStatus.temperatures || []; + + // Group temperatures by location + const groups = {{ + cpu1: [], cpu2: [], nvme: [], raid: [], ambient: [], exhaust: [], inlet: [], pcie: [], chipset: [], other: [] + }}; + + temps.forEach(t => {{ + const loc = t.location || 'other'; + if (groups[loc]) groups[loc].push(t); + else groups.other.push(t); + }}); + + // Render CPU 1 Cores + const cpu1El = document.getElementById('temp-cpu1'); + if (groups.cpu1.length > 0) {{ + const cores = groups.cpu1.filter(t => t.name.toLowerCase().includes('core')); + const others = groups.cpu1.filter(t => !t.name.toLowerCase().includes('core')); + let html = '

🖥️ CPU 1

'; + cores.forEach((t, i) => {{ const cls = t.value > 70 ? 'high' : t.value > 50 ? 'medium' : 'low'; - return `
- ${{t.name}} - ${{t.value.toFixed(1)}}°C -
`; - }}).join(''); - }} + html += `
Core ${{(i+1)}}${{t.value.toFixed(1)}}°C
`; + }}); + others.forEach(t => {{ + const cls = t.value > 70 ? 'high' : t.value > 50 ? 'medium' : 'low'; + const label = t.name.toLowerCase().includes('package') ? 'Package' : t.name; + html += `
${{label}}${{t.value.toFixed(1)}}°C
`; + }}); + cpu1El.innerHTML = html + '
'; + }} else cpu1El.innerHTML = ''; + + // Render CPU 2 Cores + const cpu2El = document.getElementById('temp-cpu2'); + if (groups.cpu2.length > 0) {{ + const cores = groups.cpu2.filter(t => t.name.toLowerCase().includes('core')); + const others = groups.cpu2.filter(t => !t.name.toLowerCase().includes('core')); + let html = '

🖥️ CPU 2

'; + cores.forEach((t, i) => {{ + const cls = t.value > 70 ? 'high' : t.value > 50 ? 'medium' : 'low'; + html += `
Core ${{(i+1)}}${{t.value.toFixed(1)}}°C
`; + }}); + others.forEach(t => {{ + const cls = t.value > 70 ? 'high' : t.value > 50 ? 'medium' : 'low'; + const label = t.name.toLowerCase().includes('package') ? 'Package' : t.name; + html += `
${{label}}${{t.value.toFixed(1)}}°C
`; + }}); + cpu2El.innerHTML = html + '
'; + }} else cpu2El.innerHTML = ''; + + // Render NVMe + const nvmeEl = document.getElementById('temp-nvme'); + if (groups.nvme.length > 0) {{ + let html = '

💾 NVMe SSD

'; + groups.nvme.forEach((t, i) => {{ + const cls = t.value > 70 ? 'high' : t.value > 50 ? 'medium' : 'low'; + html += `
NVMe ${{(i+1)}}${{t.value.toFixed(1)}}°C
`; + }}); + nvmeEl.innerHTML = html + '
'; + }} else nvmeEl.innerHTML = ''; + + // Render RAID + const raidEl = document.getElementById('temp-raid'); + if (groups.raid.length > 0) {{ + let html = '

🔒 RAID Controller

'; + groups.raid.forEach((t, i) => {{ + const cls = t.value > 70 ? 'high' : t.value > 50 ? 'medium' : 'low'; + html += `
Controller ${{(i+1)}}${{t.value.toFixed(1)}}°C
`; + }}); + raidEl.innerHTML = html + '
'; + }} else raidEl.innerHTML = ''; + + // Render Ambient + const ambientEl = document.getElementById('temp-ambient'); + if (groups.ambient.length > 0 || groups.exhaust.length > 0 || groups.inlet.length > 0) {{ + let html = '

🌡️ Ambient / System

'; + [...groups.ambient, ...groups.exhaust, ...groups.inlet].forEach(t => {{ + const cls = t.value > 40 ? 'high' : 'low'; + const label = t.location === 'exhaust' ? 'Exhaust' : t.location === 'inlet' ? 'Inlet' : 'Ambient'; + html += `
${{label}}${{t.value.toFixed(1)}}°C
`; + }}); + ambientEl.innerHTML = html + '
'; + }} else ambientEl.innerHTML = ''; + + // Render Others + const otherEl = document.getElementById('temp-other'); + const others = [...groups.pcie, ...groups.chipset, ...groups.other]; + if (others.length > 0) {{ + let html = '

📊 Other Sensors

'; + others.forEach(t => {{ + const cls = t.value > 70 ? 'high' : t.value > 50 ? 'medium' : 'low'; + html += `
${{t.name}}${{t.value.toFixed(1)}}°C
`; + }}); + otherEl.innerHTML = html + '
'; + }} else otherEl.innerHTML = ''; // Fan grid const fans = currentStatus.fans || [];