You are browsing as a guest. Sign up (or log in) to start making projects!

Thermals

  • 13 Devlogs
  • 34 Total hours

A desktop app for displaying thermal and load information about your machine, written in Java.

Ship #1

Hi! Welcome to my project, Thermals.

########

It is a system resource monitor for Windows and Linux, written in Java.

It monitors the following:

  • CPU (usage, frequency, temperature)
  • RAM (usage, free, on linux also cached)
  • GPU (usage, temp, VRAM usage)
  • Disks (name, mountpoint, read/write, usage)
  • Network (adapter name, download/upload)

Known Issues:

  • Intel GPUs under Windows only report temperature correctly due to intel not really making it possible to read GPU data like you can with NVAPI/ADLX
  • Intel GPUs under Linux do not show up at all
  • AMD GPUs under Linux are untested and may not work (due to me not having AMD hardware avail, on windows a friend tested it for me)

Tested on:

  • Windows (Lenovo LOQ Gaming 15IRH8; i7-13620H, NVIDIA RTX 4050 Laptop GPU)
  • WSL (same lenovo as above)
  • Windows (Custom Build; AMD Ryzen 7 something, AMD Radeon something)
  • Ubuntu 25.10 (Dell Latitude 5410; Stock)

It works by polling hardware data on a background thread and pushing updates to the UI via a listener system. Data sources differ by platform:

On windows, data comes from OSHI (a java library), D3DKMTHK for mainly GPU count and temperature on intel GPUs, NVAPI for NVIDIA GPUs and ADLX for AMD GPUs. The last three use an external C++ helper which interacts with these libraries and returns a json structure to the java app via stdout, which contains all the detected values.

On Linux, data comes from OSHI, nvidia-smi and hwmon.


The UI is built with Java Swing and FlatLaf for a dark, modern, Jetbrains-IDE-like style.
For graphs, JFreeChart was used. The App also has a system tray icon, of which the color indicates the current CPU temperature.

########

I hope you have fun trying my project! :)

  • 13 devlogs
  • 34h
  • 13.98x multiplier
  • 480 Stardust
Try project → See source code →
Open comments for this post

6h 22m 56s logged

Everything finally works!!

I added support for linux and tested on WSL and native Ubuntu. Everything works perfectly (except AMD GPUs on Linux, didn’t have any hardware to test that…)

In the last two days, a lot of changes happened, which are listed below.


Changelog

August 19th:

  • Window immediately opens on app start now
  • App now works without a tray icon
  • Remove fan speed display
  • Add CPU temp sensing for linux
  • Make Disk and Net Panels grow on more entries that can fit
  • Add filter for unwanted mounts/filesystems on disks view
  • Hide middle panel (GPUs) if no valid GPU is present (mainly happens on linux + intel gpu)
  • Implement GPU stat reading for NVIDIA and AMD GPUs in Linux
  • Switch to JBR (Jetbrains Runtime) to fix scaling issues on Linux
  • Create & debug CI/CD pipeline (a sh*t ton of debugging mostly)
  • Add the logo
  • Add file lock for only one instance
  • Add PawnIO install prompt

August 20th:

  • Overhaul the tray icon behaviour and window controls
  • Switch RAM graph to percentages from absolute values
  • Add EMA filter for CPU temperature
  • Add temperature data to CPU and GPU graphs
  • Add color coded font for stats corresponding to graph datasets
  • Fix up popups and the main class
  • Clean up and optimize the whole app a little
  • Fix Linux app launch
  • Hide the AppImage mount under Linux

… and of course tons of tiny tweaks and fixes everywhere too. :)

0
0
7
Open comments for this post

2h 19m 16s logged

All Sensor Data works now! :)

(on windows at least)

Disks

Per disk, you get its name and mountpoint, its R/W and its current capacity (used/total GB, progress bar and percentage).

Network Adapters

Per adapter, you get name and up/down speeds.
Names above 40 chars are shortened to avoid text of the speed and name colliding.


Next Up

I’m working on getting Linux working too. Will probably have that done by tomorrow.

0
0
51
Open comments for this post

55m 15s logged

RAM Panel and ADLX works!

(yes, i did the adlx part partially using claude because i don’t hate myself enough to work on the adlx stuff for 5h when i have to get up tomorrow)

0
0
37
Open comments for this post

3h 38m 45s logged

CPU and GPU data working!

The Data Sources

For CPU, mostly OSHI. For CPU frequency, I’ve also decided to go back to OSHI for various reasons. CPU temperature is queried using PawnIO.
For GPU(s), D3DKMTHK is used for a list of GPUs and GPU temperature. For all other metrics, NVAPI (NVIDIA API) is used. AMD GPUs will also get support in the near future (via ADLX), Intel GPUs won’t be supported though.

The Architecture of the PawnIO Reader Data Path

The Hardware Manager calls the method requestData in WindowsReader which hands it a SensorData object, which contains the CPU temperature and a list of GpuData object, which look like this:

public record GpuData(
    String name,
    double tempC,
    double usagePct,
    long vramUsedMb,
    long vramTotalMb
) {}

This data is then passed to all subclasses of the hardware manager that need it (Cpu, Gpu).


Other Improvements

The hardware manager now has a new method called addUpdateListener with which you can register a class that implements the HwUpdateListener interface. The hardware manager will then call onHwUpdate on all registered classes as soon as it has refreshed its data via OSHI and PawnIO-Reader.

Additionally, the fan panel will not be displayed on windows because of reasons mentioned in the last devlog (too time-consuming to implement properly)

0
0
5
Open comments for this post

2h 9m 14s logged

f*ck microsoft

After MANY hours of research and wanting to launch this project into orbit WAY too many times, I’ve finally managed to query almost all of the missing and/or incorrect data in windows (CPU frequency and temp and all GPU stuff) except fan speeds i just dont care enough anymore to implement that too (why later).


Why this is SO complicated

In contrast to linux (which has hwmon), windows has no standardized way of getting proper sensor data reliably. CPU temp (accessible via WMI) is often not properly exposed by the manufacturer causing it to return either zero or garbage. CPU frequency is exposed, but it kinda lags behind and is measured/calculated badly. GPU stuff is basically not exposed at all, expect via their half-working API called “D3DKMTHK” (no i did not smash my keyboard) over which you can pretty reliably get GPU temp and memory frequency, but usage and fan speed not so much. For that, I used NVAPI (NVIDIA’s GPU query API).
 

What? AMD and Intel GPUs don’t work with NVAPI?
i know and i will not fix it, i don’t have the energy or time for that (i’m sorry). you’re welcome to give me a PR tho

 
For the CPU stuff (frequency and temperatue) I used PawnIO, a kernel driver that can be scripted to do a lot of things. I use premade “AMX Modules” which basically are such scripts to get these CPU metrics.
The AMX modules in use are:

  • IntelMSR
  • AMDFamily17
  • RyzenSMU

(you can find these here)


The Final Solution

A C++ shim which takes the data from PawnIO, NVAPI, “D3DKMTHK” and all the others and hands it to the java app via stdout. The java process runs the .exe everytime it needs the values, parses the returned json and saves the values.


What were u talking about fan speeds too difficult again?

You see, I could just do the same as with the CPU stuff (AMX modules). The problem is, the module LpcIO which exposes the EC (embedded controller) only exposes a direct path to it, meaning I’d have to implement and parse everything myself. The huge problem with this is: on laptops the EC is vendor-specific and undocumented, and on desktop, there are ~71 supported chips that require different implementations, which is probably the biggest waste of time, so I’ve decided to just skip fan speeds entirely.

0
0
6
Open comments for this post

3h 31m 23s logged

Partial Live CPU Data working! :)

I’ve managed to get the live CPU stats (usage, per-core usage and (approx.) clock speed) and the CPU usage graph running.

One problem with the current approach for measuring values (which is done using OSHI) is that on Windows, things like CPU temperature, CPU clock speed and others are not reliable.


Why?

On Windows, metrics like CPU temperature are read over WMI. However, the actual CPU temp is often only partially or not at all correctly exposed via WMI. CPU clock is often a stale/cached value or sometimes not at all given.
 
This requires an external source of data which is both correct and more reliable.

Technical Architecture of HwManager and live stats/graphs

The hardware manager is a class that can provide all sensor data necessary. It abstracts OSHI and any future methods of aquiring data into one class (with instances of other classes such as Cpu).
It has its own thread which calls the pollValues method of all subclasses (Cpu, …) which then update their internal values, which can be retrieved via getter functions.

The Window class has an internal timer which calls the update method of TopPanel, MiddlePanel and BottomPanel, which then call each component panel’s update method which then update their stats and graphs.

0
0
4
Open comments for this post

2h 3m 51s logged

Fan Panel and Disks Panel done!

After once again a little time away from this project, I finally finished the fan panel and the disks panel! :)


Fan Panel

The fan panel has a 2x3 grid which expands in columns if more than 6 fans are present (which also expands the width of the panel). Each fan is just a Stat instance.

Disks Panel

Each Disk is given params such as name, type (NVMe, SATA SSD/HDD, …), usage percentage and read/write rates. Then, the Disk instance manages the layout and drawing.
 
The Disk class extends BaseBottomEntry, which is a horizontal JPanel with a BoxLayout and a name label. Then, Disk adds a JPanel on the right side of itsself and places stats like the ones given above (type, read/write activity, …) in it. For usage, there’s also a PercentageBar which is also custom-written.

Looking forward to finishing the UI and then getting started on the actual stats reading! :)

0
0
1
Open comments for this post

2h 30m 57s logged

UI coming together even more!

The core UI structure is done now. This includes:

  • Top Row
  • Middle Row
  • Bottom Row

Top Row

The top row contains CPU and RAM, same as in the last devlog.

Middle Row

The middle row contains all GPUs and fan speeds. This means it can contain 2..n component panels (if n is number of GPUs minus one).
It is horizontally scrollable which prevents this row over-cluttering the popup (which would be caused by methods like wrapping excess panels to the next row).

Bottom Row

This row contains two panels which fill the window’s width. The first panel - the disks panel - contains info about all disks or drives in the computer. It will have one “entry” (one row inside the panel with info such as drive name, transfer speed and used/total size).
 
Same goes for the network panel, which contains all network adapters. It will display info such as download, upload, adapter state and name.

0
0
3
Open comments for this post

4h 17m 14s logged

UI Overhaul!!!!

I’ve decided I wanna go for a slightly different UI style, with CPU and RAM in the first row in a 2:1 ratio. Below, there’s the GPU row with 2 cols and as many rows as needed, and below will be one panel for all disks (including their usage, current transfer and so on) and one for all network adapters and their stats.


What changed already

The CPU and RAM panel are now positioned exactly how they will be in the final product. The CPU panel is also basically done, as its got the usage graph on top and stats on the bottom.

Technical Details

There are two new classes: Stat and Graph. A Graph is… well pretty self explanatory I hope, and a Stat is one value with text on what it is. (as seen below the red graph).

0
0
2
Open comments for this post

1h 57m 34s logged

UI Overhaul!! :)

I finally got the UI working in a way I like. You now have one panel per component.

The Structure

The window contains a JScrollPane (for scrolling when the content gets larger than the window) which contains a JSplitPane for dividing the contents into top and bottom.
 
Additionally, there are the TopPanel and BottomPanel. The TopPanel contains three fixed panels: CPU, GPU and RAM. (still need to figure out how to properly display multi-GPU setups like this but future problem i guess)
The BottomPanel contains all other devices, like drives and network adapters.


Technical Details

Both TopPanel and BottomPanel are containers for individual “component panels”. Each component panel (CpuPanel, DiskPanel, …) owns its own components like labels, graphs or similar. I also wrote a custom JPanelRounded class for rounded panels.

About to add a little detail to the component panels next! :)

0
0
2
Open comments for this post

3h 20m 37s logged

Finally, progress again!

After being offline for a little touching… grass and stuff (idk if anyone will get the reference) I finally got to work again and made two things work:

  1. Right Click Menu for the Tray Icon
  2. Basic Popup Window Structure

The Window Architecture

The popup window uses one main JSplitPlane which houses two panels (TopPanel, BottomPanel). Each of these panels again contains panels (CpuPanel, GpuPanel, …), of which each one contains stuff like its own labels and other stuff.

0
0
4
Open comments for this post

49m 32s logged

Tray Icon is nearing completion (already)!

OK, don’t take it wrong: the app is nowhere near finished but at least the tray icon is!


The current tray icon state

The tray icon now displays the CPU temperature represented as a color, interpolated between a cold hue (green, 30°C) and a hot hue (red, 90°C). Also, I added a tooltip which shows temps for CPU and GPU (currently its placeholders but oh well)

It took embarassingly long for me to realise I needed antialiasing to eliminate the choppyness-look from the icon btw

0
0
3
Open comments for this post

24m 50s logged

New project alert!

I’ve started working on an app called “Thermals”. It serves the purpose of being a simple yet modern and elegant usage and temperature monitor, accessible through a tray icon, made to work on both Windows and Linux.


Current Progress

Build System, Repository and similar is set up and simple tray icon (a white square) is also working.

Looking forward to how this project comes out! :)

0
0
2

Delete project?

Are you sure you want to permanently delete this project? This action cannot be undone.

All devlogs, followers, and associated data will be removed.

Followers

Loading…