framework already has a published GUI interface for controlling the backlight of the number pad and keyboard together. How can I use that to change the backlight of both the modules based on the ambient light sensor?
I have seen that the keyboard backlight of MacBooks automatically turn on in a dark or poorly lit room I would like to have that same for my framework 16.
I have zero experience with QMK and wanted to learn more about.
This would be very nice. I have no idea about how to access the light sensor from the OS, but if you manage to read the values it could definetly be done…
A quick search got me this from Reddit. Maybe useful!
If you’re asking about the windows scripting part, I can’t help there, I don’t use windows. I don’t know what’s good and easy.
For the qmk part, the part that is controlling the keyboard backlights, that I can help with. For example, this should be the command to set the numpad backlight to 50 percent: qmk_hid --vid 32ac --pid 0014 via --backlight 50
Here are the pid “product ID” codes for FWL16 keyboards
So the way you might want it to go is, the script checks the ambient light sensor, perhaps using the api that TheLPeink linked to, stores the value, checks if the value differs more than a choosen threshold from the last check, if it does, then ramp the keyboard backlights to match by sending repeated commands to change the backlights progressively.
ANSI and the numpad and I did try a PowerShell script with a lot of help from grok, but it seems that the ambient light sensor is not accessible using the API TheLPeink linked to. Here is the script that grok gave me.
# Framework Laptop 16 Keyboard Backlight Control Script
# Controls backlight for PIDs 0012 and 0014 using ambient light sensor and display state
# Requires qmk_hid tool installed and accessible
# Configuration
$QMK_HID_PATH = "qmk_hid" # Path to qmk_hid.exe (update if not in PATH)
$BRIGHT_ENOUGH_THRESHOLD = 100 # Lux value where keys are visible without backlight
$POLL_INTERVAL = 1 # Seconds between checks
$DEVICE_PIDS = @("0012", "0014") # Framework Laptop 16 keyboard PIDs (ANSI Keyboard, Numpad)
$VID = "32ac" # Framework vendor ID
# Logging setup
$LogFile = "$PSScriptRoot\backlight_control.log"
function Write-Log {
param($Message)
$timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
"$timestamp - $Message" | Out-File -FilePath $LogFile -Append
Write-Host "$timestamp - $Message"
}
# Function to set backlight brightness for a device
function Set-BacklightBrightness {
param (
[string]$PID,
[int]$Brightness
)
if ($Brightness -lt 0 -or $Brightness -gt 100) {
Write-Log "Invalid brightness value: $Brightness"
return
}
try {
$command = "& $QMK_HID_PATH --vid $VID --pid $PID via --backlight $Brightness"
Write-Log "Executing: $command"
Invoke-Expression $command
} catch {
Write-Log "Error setting backlight for PID $PID : $_"
}
}
# Function to get ambient light sensor value
function Get-AmbientLight {
try {
Add-Type -TypeDefinition @"
using System;
using System.Runtime.InteropServices;
public class PowerManagement {
[DllImport("user32.dll")]
public static extern IntPtr RegisterPowerSettingNotification(IntPtr hRecipient, ref Guid PowerSettingGuid, int Flags);
[DllImport("user32.dll")]
public static extern bool UnregisterPowerSettingNotification(IntPtr handle);
public static readonly Guid GUID_MONITOR_POWER_ON = new Guid("02731015-4510-4526-99e6-e5a17ebd1aea");
}
"@
$lightSensor = [Windows.Devices.Sensors.LightSensor]::GetDefault()
if ($null -eq $lightSensor) {
Write-Log "No ambient light sensor found."
return $null
}
$reading = $lightSensor.GetCurrentReading()
if ($null -eq $reading) {
Write-Log "Failed to read ambient light sensor."
return $null
}
$lux = $reading.IlluminanceInLux
Write-Log "Ambient light: $lux lux"
return $lux
} catch {
Write-Log "Error reading ambient light sensor: $_"
return $null
}
}
# Function to check if display is off
function Test-DisplayOff {
try {
$monitorOn = Get-CimInstance -Namespace root\wmi -ClassName WmiMonitorPowerOn
$isOff = $monitorOn | Where-Object { $_.MonitorPowerOn -eq $false }
if ($isOff) {
Write-Log "Display is off."
return $true
}
Write-Log "Display is on."
return $false
} catch {
Write-Log "Error checking display state: $_"
return $false
}
}
# Main loop
function Start-BacklightControl {
Write-Log "Starting backlight control script."
while ($true) {
try {
# Check display state
if (Test-DisplayOff) {
foreach ($pid in $DEVICE_PIDS) {
Set-BacklightBrightness -PID $pid -Brightness 0
}
Start-Sleep -Seconds $POLL_INTERVAL
continue
}
# Read ambient light
$lux = Get-AmbientLight
if ($null -eq $lux) {
Start-Sleep -Seconds $POLL_INTERVAL
continue
}
# Adjust backlight
if ($lux -gt $BRIGHT_ENOUGH_THRESHOLD) {
$brightness = 0 # Turn off in bright conditions
} else {
# Map lux to brightness (0-100%)
$brightness = [math]::Max(0, [math]::Min(100, [int]((1 - $lux / $BRIGHT_ENOUGH_THRESHOLD) * 100)))
}
Write-Log "Setting brightness to $brightness%"
foreach ($pid in $DEVICE_PIDS) {
Set-BacklightBrightness -PID $pid -Brightness $brightness
}
} catch {
Write-Log "Unexpected error: $_"
}
Start-Sleep -Seconds $POLL_INTERVAL
}
}
# Start the script
try {
Start-BacklightControl
} catch {
Write-Log "Script terminated: $_"
}