Monitor Windows PC (temp, load, etc.)

Thats an option, but it doesn’t look like pulling temp and load for a CPU and GPU are supported.

My main use for this is an HTPC that is in a cabinet with my other stereo equipment and modem/router ect. I want to see if it is getting to hot in there and also monitor load as it transcodes for remote viewing and how hot the GPU is getting when it is being used.

I’ve never used Open Hardware Monitor, but a quick look at the web page reveals that it publishes its data to WMI. I don’t think there’s currently a WMI component for HA, but it might be an interesting addition. That doesn’t help you, of course, but it does get me thinking about how hard it would be to add WMI to HA.

It looks like you might not even need a new HA component - there’s a WMI command line interface, and you might be able to use the Command Line Sensor.

With Open Hardware Monitor running on your PC, try the following command:

wmic /namespace:\\ROOT\OpenHardwareMonitor path Sensor get name, identifier, sensortype, value

If that gives you a table of sensors and values (it does on my PC) then we should be able to figure out the right command to spit out the sensor data you want, and the right value_template to get the Command Line Sensor to extract the value.

The question is how to get that data to a remote HA instance. This is why I was thinking of going the route of pulling data from the web page (ie the scrape sensor) but I wasn’t sure if there was a cleaner way.

I can see what you proposed working on the same system, however, I run HA on a Raspberry Pi and want to monitor a separate windows PC. They are all on the same network and the Open Hardware Monitor page can be opened from any computer on the network so I assume HA should be able to see and digest the data from the web page.

There’s an HTTP Scrape sensor, but I’ve never used it, and I’m not sure it’s flexible enough to do what you want.

Another option might be to write some code in the language of your choice that runs on the PC, does the WMI command, then posts the updates to HA using the HTTP Sensor model.

Just a thought; would SNMP be an option? I’m currently using it to monitor uptime on my Win10 boxes.

Do you know if the remote pull from a windows 7 computer is available. My HTPC is running windows 7.

I don’t see why not; the basic MIBs haven’t changed much.

Just came across this. How about using Speedfan with this? SFSNMP isn’t being developed, but this works with speedfan. Also what about this, it seems to work with Open Hardware Monitor. I really do want to get this to work within HA.

None of the WMI classes seemed to be available to me, and I was getting frustrated. I resorted to something messy, probably error prone, and definitely not memory efficient. I don’t care. It works. Read on if you’re interested.

You will need

  • HWInfo
  • A share exposing a directory readable by HA to the rest of the network
  • A Windows host running Powershell version 5+

Docker

If you’re running a container, and you didn’t bind the /config directory to the host filesystem when you first built it, you’ll need to rebuild. I just tarred the whole config directory, copied it out of the container, built anew with

docker run –v /home/cooldude/.homeassistant/config:/config etc etc etc

then untarred into ~/.homeassistant/config.

Samba

Create a share for the Windows hosts to write their sensor logs. You’d obviously need to enter your username or @groupname in valid users

[homeassistant] 
path = /home/cooldude/.homeassistant 
valid users = @smbgrp 
browsable = yes 
writable = yes 
read only = no

HWInfo

On the Windows hosts whose temps we want to monitor, we need to install HWInfo, set it to auto-run, set the sensors we want to log and start logging.

First, the HWInfo config. I reduced the monitored sensors to just what I wanted: core average and max temperatures.

General : Set temperature units and polling rate.

Layout : Use the Monitoring checkbox to disable the unwanted sensors. You can hold ctrl to select multiple rows to uncheck.

So I ended up with a pretty restricted list of things to monitor. Glances takes care of everything else I’m interested in.

Use this icon to start logging to a CSV.

beh

Set this to a local directory. We’ll massage this data before dumping it on the share.

Logging cannot be started automatically. If the computer reboots, you’ll have to go in and click this button again. The developers have intentionally left this need unfulfilled, as is explained in this thread.

Fully automated monitoring/reporting is reserved for the HWiNFO SDK, which is a commercial product.

I haven’t found recent evidence of anyone implementing the SDK in a way that would help us here, so this is glaring flaw #1.

Powershell

Things we need to achieve here.

  • Get the headers from the CSV, remove characters that homeassistant won’t like, and rename duplicate headers where two sensors return the same data, like Core 0 Avg Temp C for each CPU.
  • Ensure that temperatures are expressed as integers
  • Mount our homeassistant share as a PSDrive
  • Construct a JSON object of our desired parameters and write it out to a single-line text file at the directory homeassistant is configured to check (HALogging:\config\filesensors)

The single line part of this is crucial. A file sensor only reads the last line of a file, so all our values need to be there. If you’re getting value_json.whatever is not defined in your HA log, you probably have some junk data on your final line. Or you have a typo, I guess.

If your share is secured, you’ll want to create your own $credential object to import. If not, you’ll want to remove -Credential $credential.

Plug your values into $sharePath ('\\<host>\<share>'), $logFile (the log coming from HWInfo) and $outFile (the file to be read by homeassistant).

Add the attributes you want to extract to $values. Use the names that appear in the CSV.

Create a schedule task to run Powershell on startup with -WindowStyle Hidden -File C:\Scripts\LogTemps.ps1.

#HomeAssistant Share
$sharePath = '\\10.1.1.52\homeassistant'

#Set up file share access
$credential = Import-Clixml -Path "$PSScriptRoot\Cred_HALogging.xml"
New-PSDrive -Name HALogging -PSProvider FileSystem -Credential $credential -Root $sharePath -ErrorAction Stop

$logFile = "$env:ProgramData\Logs\HWInfo\sensors.CSV"
$outFile = "HALogging:\config\filesensors\deathknell.txt"

#Set trap to unmount PSDrive if breaking error is encountered
trap {
    Remove-PSDrive -Name HALogging
}

##################################
### SELECT PARAMETERS TO QUERY ###
##################################

$values = @(
    #Add value headers here as they appear in the CSV

    'Date',
    'Time',
    'Core Temperatures (avg) [°C]',
    'Core Max [°C]'
    
) | ForEach-Object {
    $_ -replace '[^a-zA-Z0-9 ]',''
}
$valueList = [System.Collections.ArrayList]::new()

########################
### ASSEMBLE HEADERS ###
########################

#Get headers from CSV. Clean unfriendly characters and whitespace.
$headersRaw = Get-Content $logFile | Select-Object -First 1
$headersRaw = @($headersRaw -split ',').Where({![string]::IsNullOrWhiteSpace($_)}).Foreach({$_ -replace '\s{3,}.*$','' -replace '[^a-zA-Z0-9 ]',''})

#Find duplicate headers and construct a table of replacements
Remove-Variable replace -ErrorAction Ignore
[object[]]$replace = @()
$headersRaw | Group-Object | ForEach-Object {
    $string = $_.Name
    $idxs = 0..$headersRaw.Count | Where-Object {$headersRaw[$_] -eq $string}
    Write-Debug "$string appears at indexes $($idxs -join ',')"
    for ($i=0;$i-lt$_.Count;$i++) {
        $prepend = ''
        if ($_.Count -gt 1) {
            $prepend = "CPU$i "
        }
        $replaceObj = New-Object psobject -Property @{
            Index = $idxs[$i]
            OldVal = $string
            NewVal = "$prepend$string".Replace(' ','_')
        }
        [object[]]$replace += $replaceObj
    }
}

#Construct new headers from the replacement table
$headers = @()
$headers = $replace | Sort-Object -Property Index | Select-Object -ExpandProperty NewVal

#################
### MAIN LOOP ###
#################

while ($true) {

    #Import last line of the CSV using the new headers, and selecting the values from $values.
    $tempData = Import-Csv -Header $headers -Path C:\ProgramData\logs\HWInfo\sensors.CSV | Select -Last 1 | Select-Object $valueList

    #Express all numeric values as Int32
    $Ints = $tempData.psobject.properties | Where-Object {$_.Value -match '^\d+$'}
    foreach ($prop in $Ints) {
        $Name = $prop.Name
        $Val  = $prop.Value
        $tempData.$Name = $Val.ToInt32($null)
    }

    #Write to terminal
    $tempData | Out-Host

    #Output as JSON
    $tempData | ConvertTo-Json -Compress | Out-File $outFile -Encoding ascii -Force

    #Delay and reset
    Start-Sleep -Seconds 15
    Clear
}

HomeAssistant config

I created a directory just for the text files, 'cause it’s probably gonna get messy in there. From the container’s perspective, this is /config/filesensors.

This requires us to whitelist the directory with the following change to configuration.yaml.

homeassistant: 
  allowlist_external_dirs: 
  - "/config/filesensors"

Then we create out sensors. I’ll just show the one here. I created one of these for each value I’m extracting from the JSON.

sensor: 
  - platform: file 
    name: 'Deathknell CPU0 Avg Temp C' 
    file_path: /config/filesensors/deathknell.txt 
    value_template: '{{ value_json.CPU0_Core_Temperatures_avg_C }}' 
    unit_of_measurement: "°C"

If the config passes validation, restart HA.

We have sensors!
beh

Yaaay! (Values on the left are from Glances)

So yeah. It works, and can theoretically work for anything that HWInfo can report on.

Glaring flaw #2 is the fact that we’re creating an additional entity for each sensor, instead of one object with attributes. If this were a REST API, I would define my endpoint and declare all the attributes I want to pull from it. Here, we’re telling HA to read the same file over and over again, targeting a new attribute each time. json_attributes is not a valid parameter for the file sensor. I tried.

2 Likes

Has anyone figured out a good solution yet? I’m not interested in reading from a CSV file and manually having to enable a setting after each reboot.

Things I’ve tried:

Have a look at HASS Workstation

Thanks. But, that unfortunately won’t work.

However, I got very lucky. HWiFO64 has RESTful web server addon that works great! I assumed it wouldn’t work because of how old it was; but, to my surprise, it works perfectly; and, the ONLY good solution I could find that doesn’t require unnecessarily writing to disk/text file/windows registry:

Best Solution:

I hope this helps anyone else on Windows who wants to display CPU temps and other hardware details that Glances doesn’t have access to.

1 Like

Can you please post a tutorial for implementing this? I would like to be able to see my PC CPU temperatures from Home Assistant. (HA is running on an Intel NUC in my basement).

Thanks

1 Like

I definitely will sometime this weekend. I still need to add the sensor to my HA. There is one small caveat. The free version of HWINFO has a 12.hour limit to use this feature (shared memory access). I’ll have to pay $25 for the Pro version of HWINFO to have it running 24/7.

Sorry wrong one, I use this and it does have CPU temperature

Have you looked at CoreTemp? It’s free and there is an SDK written in C++.

Yes, I looked at CoreTemp. Who is going to download the SDK, learn how it all works, then write a RESTful web server addon from scratch in C++ for it? :slight_smile:

Not me… I can barely get my Arduino code to work.

I’m happy to say my proof of concept was successful. I am able to display a “CPU core temperature” in as a Home Assistant sensor from my Windows 11 PC via HWinfo. Basically, anything HWINFO has access to, it can be displayed in Home Assistant. All sorts of interesting sensors, I.E., SSD Disk life % left, CPU wattage, fan speeds, etc.

I’ll post a complete “how-to” once I add all the sensors I want to add for myself. There really isn’t much to it.
test

configuration.yaml
Below, is the actual working code I’m using to extract the sensor value (updated every 6 seconds) for the sensor in the green rectangle above.

rest:
  - resource: http://192.168.1.249:55555/
    sensor:
      - name: "CPU Package Temperature"
        value_template: "{{value_json 
                          | selectattr('SensorClass', 'equalto', 'CPU [#0]: Intel Core i7-4790K: DTS') 
                          | selectattr('SensorName', 'equalto', 'CPU Package') 
                          | map(attribute='SensorValue') 
                          | first}}"
        unit_of_measurement: 'ºC'
    verify_ssl: false
    timeout: 30
    scan_interval: 6
``