Tips en Trucs 2026

Omgevingslicht meten met webcam

Vandaag demonstreren we de voordelen van Open Source met een praktijkvoorbeeld. We maken kennis met het GitHub project Lumos. Daarna passen we de broncode aan om er een lichtmeter van te maken.

Lumos is een intelligent achtergrond programma (daemon) die zorgt voor een automatische helderheidsregeling. Het past de helderheid van het scherm aan op basis van het omgevingslicht dat door de webcam wordt geregistreerd, zonder dat er afbeeldingen worden opgeslagen. Lumos heeft een realtime bediening, een desktop-GUI en een terminalinterface (TUI).

Lumos kenmerken

Lumos vereisten

M.a.w. de meeste recente distributies op een laptop met webcam voldoen aan de eisen, ook Debian 13 Trixie.

Lumos installeren

Lumos is niet beschikbaar via een softwarebron, maar kan enkel geïnstalleerd worden via de broncode. De Lumos ontwikkelaar stelt voor de installatie een eenvoudige doch duidelijke handleiding en een installatiescript ter beschikking. M.a.w. goed gedaan.

De broncode downloaden

Start een terminal en download (kloon) de GitHub broncode met de volgende opdracht:

dany@pindabook:~$ git clone https://github.com/anilaras/lumos.git
Cloning into 'lumos'...
remote: Enumerating objects: 63, done.
remote: Counting objects: 100% (63/63), done.
remote: Compressing objects: 100% (44/44), done.
remote: Total 63 (delta 30), reused 47 (delta 17), pack-reused 0 (from 0)
Receiving objects: 100% (63/63), 29.23 KiB | 7.31 MiB/s, done.
Resolving deltas: 100% (30/30), done.

Open in de terminal de map met de broncode:

dany@pindabook:~$ cd lumos/

Het installatiescript

Bij het uitvoeren van het installatiescript bleek het script een fout te bevatten. Hoewel dit tegenstrijdig klinkt, is ook dit een voordeel van Open Source. Ik constateerde de fout, bekeek het script, zag een oplossing en kon zo de fout wegwerken. Ondertussen heb ik de ontwikkelaar een Push bericht met de aanpassing gestuurd. Indien de ontwikkelaar daar positief op reageert, kan de fout als je dit leest al weggewerkt zijn. Je kunt de fout in het installatiescript zelf wegwerken door een teksteditor (nano) met het aan te passen script te starten:

dany@pindabook:~/lumos$ nano -P -B -l install.sh  

Waarschijnlijk is door een onoplettendheid een regel uit het script verdwenen. Onder regel
132 # 4.6 GUI INSTALLATION
ontbreekt de regel
133 if [ "$INSTALL_GUI" = true ]; then

 GNU nano 8.4                                        install.sh *                                                 
121
122 echo "TUI installed to: $TUI_INSTALL_PATH"
123
124 # 4.5 TUI INSTALLATION
125 if [ "$INSTALL_TUI" = true ]; then
126     echo -e "${YELLOW}[4.5] Installing TUI...${NC}"
127     sudo cp "$TUI_NAME" "$TUI_INSTALL_PATH"
128     sudo chmod +x "$TUI_INSTALL_PATH"
129     echo "TUI installed to: $TUI_INSTALL_PATH"
130 fi
131
132 # 4.6 GUI INSTALLATION
133 if [ "$INSTALL_GUI" = true ]; then
134     echo -e "${YELLOW}[4.6] Installing GUI...${NC}"
135     sudo cp "$GUI_NAME" "$GUI_INSTALL_PATH"
136     sudo chmod +x "$GUI_INSTALL_PATH"

^G Hulp         ^O Opslaan      ^F Zoeken       ^K Knippen      ^T Opdracht     ^C Positie      M-U Terugdraaien
^X Afsluiten    ^R Inlezen      ^\ Vervangen    ^U Plakken      ^J Uitvullen    ^/ Naar regel   M-E Herdoen

Pas dit aan en sla de aanpassing op met de sneltoets Ctrl+o, gevolgd door Return. Sluit de nano editor af met de sneltoets Ctrl+x.

Maak het installatiescript uitvoerbaar:

dany@pindabook:~/lumos$ chmod +x install.sh

En voer het uit (start het):

dany@pindabook:~/lumos$ sudo ./install.sh
[sudo] wachtwoord voor dany:  
### Lumos Installation Wizard ###
Starting system-wide (Root) installation...

[1/5] Checking prerequisites...
Do you want to install the Terminal UI (lumos-tui)? [y/N]: y
[1.5/5] Checking build dependencies (NCurses)...
Error: NCurses headers not found.
Please install ncurses development libraries:
 Fedora: sudo dnf install ncurses-devel
 Debian/Ubuntu: sudo apt install libncurses-dev

Het installatiescript controleert de voorwaarden waaraan het systeem moet voldoen, en geeft gepaste meldingen als je moet ingrijpen. Mocht je de volgende foutmelding krijgen
Error: 'make' or 'gcc' not found.
installeer dan de softwarepakketten make en gcc. Dit was zoals je hieronder kunt zien op mijn Debian Trixie niet nodig:

dany@pindabook:~$ sudo apt install make gcc
[sudo] wachtwoord voor dany:  
make is reeds de nieuwste versie (4.4.1-2).
make staat ingesteld op handmatig geïnstalleerd.
gcc is reeds de nieuwste versie (4:14.2.0-1).
gcc staat ingesteld op handmatig geïnstalleerd.
Samenvatting:
 Opwaarderen: 0, Installeren: 0, Verwijderen: 0, Niet opwaarderen: 0

Na het controleren van de basisvoorwaarden, vraagt het installatieprogramma of ik de Terminal UI wil gebruiken. Ik antwoord y om het configuratieprogramma voor de terminal te installeren. Opnieuw zijn daar voorwaarden aan gebonden, deze worden na het beantwoorden van de vraag gecontroleerd.

Ik moet op mijn systeem voor de lumos-tui opdracht te installeren wel de NCurses headers installeren, wat bleek uit de melding van het installatiescript. In de melding staat ook vermeld welke opdracht je daarvoor in Fedora en Debian/Ubuntu moet gebruiken. Doen:

dany@pindabook:~/lumos$ sudo apt install libncurses-dev
[sudo] wachtwoord voor dany:  
Installeren:                               
 libncurses-dev

Voorgestelde pakketten:
 ncurses-doc

Samenvatting:
 Opwaarderen: 0, Installeren: 1, Verwijderen: 0, Niet opwaarderen: 0
 Downloadgrootte: 353 kB
 Benodigde ruimte: 2.437 kB / 84,6 GB beschikbaar

Ophalen:1 http://deb.debian.org/debian trixie/main amd64 libncurses-dev amd64 6.5+20250216-2 [353 kB]
353 kB opgehaald in 0s (4.549 kB/s)     
Voorheen niet geselecteerd pakket libncurses-dev:amd64 wordt geselecteerd.
(Database wordt ingelezen ... 206570 bestanden en mappen momenteel geïnstalleerd.)
Uitpakken van .../libncurses-dev_6.5+20250216-2_amd64.deb wordt voorbereid...
Bezig met uitpakken van libncurses-dev:amd64 (6.5+20250216-2) ...
Instellen van libncurses-dev:amd64 (6.5+20250216-2) ...
Bezig met afhandelen van triggers voor man-db (2.13.1-1) ...

Volgende poging:

dany@pindabook:~/lumos$ sudo ./install.sh
### Lumos Installation Wizard ###
Starting system-wide (Root) installation...

[1/5] Checking prerequisites...
Do you want to install the Terminal UI (lumos-tui)? [y/N]: y
[1.5/5] Checking build dependencies (NCurses)...
Do you want to install the Desktop GUI (Lumos Control)? [y/N]: y
[1.6/5] Checking Python dependencies...
Error: PyQt6 module (QtWidgets) not found.
Lumos GUI requires PyQt6. Please install it using your package manager or pip:
 Fedora: sudo dnf install python3-pyqt6
 Debian/Ubuntu: sudo apt install python3-pyqt6
 Pip: pip install PyQt6

Om ook de Desktop GUI te installeren, installeren we de PyQt6 module:

dany@pindabook:~/lumos$ sudo apt install python3-pyqt6
Installeren:                               
 python3-pyqt6

Installeren van vereisten:
 libqt6test6  python3-pyqt6.sip

Samenvatting:
 Opwaarderen: 0, Installeren: 3, Verwijderen: 0, Niet opwaarderen: 0
 Downloadgrootte: 2.808 kB
 Benodigde ruimte: 18,8 MB / 84,6 GB beschikbaar

Doorgaan? [J/n]  
Ophalen:1 http://deb.debian.org/debian trixie/main amd64 libqt6test6 amd64 6.8.2+dfsg-9+deb13u1 [191 kB]
Ophalen:2 http://deb.debian.org/debian trixie/main amd64 python3-pyqt6.sip amd64 13.10.0-1+b1 [55,0 kB]
Ophalen:3 http://deb.debian.org/debian trixie/main amd64 python3-pyqt6 amd64 6.9.0-2 [2.562 kB]
2.808 kB opgehaald in 0s (9.085 kB/s)     
Voorheen niet geselecteerd pakket libqt6test6:amd64 wordt geselecteerd.
(Database wordt ingelezen ... 206651 bestanden en mappen momenteel geïnstalleerd.)
Uitpakken van .../libqt6test6_6.8.2+dfsg-9+deb13u1_amd64.deb wordt voorbereid...
Bezig met uitpakken van libqt6test6:amd64 (6.8.2+dfsg-9+deb13u1) ...
Voorheen niet geselecteerd pakket python3-pyqt6.sip wordt geselecteerd.
Uitpakken van .../python3-pyqt6.sip_13.10.0-1+b1_amd64.deb wordt voorbereid...
Bezig met uitpakken van python3-pyqt6.sip (13.10.0-1+b1) ...
Voorheen niet geselecteerd pakket python3-pyqt6 wordt geselecteerd.
Uitpakken van .../python3-pyqt6_6.9.0-2_amd64.deb wordt voorbereid...
Bezig met uitpakken van python3-pyqt6 (6.9.0-2) ...
Instellen van libqt6test6:amd64 (6.8.2+dfsg-9+deb13u1) ...
Instellen van python3-pyqt6.sip (13.10.0-1+b1) ...
Instellen van python3-pyqt6 (6.9.0-2) ...
Bezig met afhandelen van triggers voor libc-bin (2.41-12+deb13u1) ...

En proberen we opnieuw:

dany@pindabook:~/lumos$ sudo ./install.sh
### Lumos Installation Wizard ###
Starting system-wide (Root) installation...

[1/5] Checking prerequisites...
Do you want to install the Terminal UI (lumos-tui)? [y/N]: y
[1.5/5] Checking build dependencies (NCurses)...
Do you want to install the Desktop GUI (Lumos Control)? [y/N]: y
[1.6/5] Checking Python dependencies...
PyQt6 is installed.
System is ready.
[2/5] Compiling source code...
rm -f lumos lumos-tui
gcc -O2 -Wall -o lumos main.c -lpthread
main.c: In function ‘load_config’:
main.c:102:17: warning: strncpy’ output may be truncated copying 63 bytes from a string of length 127 [-Wstringop-t
runcation]
 102 |                 strncpy(config.camera_dev, val_str, sizeof(config.camera_dev) - 1);
     |                 ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
main.c: In function ‘handle_client’:
main.c:183:14: warning: strncpy’ output may be truncated copying 63 bytes from a string of length 63 [-Wstringop-tr
uncation]
 183 |              strncpy(config.camera_dev, val, sizeof(config.camera_dev) - 1);
     |              ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
gcc -O2 -Wall -o lumos-tui lumos-tui.c -lncurses
lumos-tui.c: In function ‘load_values’:
lumos-tui.c:64:41: warning: %s’ directive output may be truncated writing up to 831 bytes into a region of size 60
[-Wformat-truncation=]
  64 |         snprintf(cmd, sizeof(cmd), "GET %s", params[i].key);
     |                                         ^~
lumos-tui.c:64:9: note: snprintf’ output between 5 and 836 bytes into a destination of size 64
  64 |         snprintf(cmd, sizeof(cmd), "GET %s", params[i].key);
     |         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Compilation successful.
[3/5] Installing binary...
Installing default config to /etc/lumos.conf...
Desktop entry created at: /usr/share/applications/lumos-gui.desktop
PyQt6 is installed.
TUI installed to: /usr/local/bin/lumos-tui
[4.5] Installing TUI...
TUI installed to: /usr/local/bin/lumos-tui
[4.6] Installing GUI...
Creating desktop entry...
GUI installed to: /usr/local/bin/lumos-gui.py
Desktop entry created at: /usr/share/applications/lumos-gui.desktop
[4/5] Creating Systemd service...
Service file created: /etc/systemd/system/lumos.service
[5/5] Enabling service...
Created symlink '/etc/systemd/system/multi-user.target.wants/lumos.service' → '/etc/systemd/system/lumos.service'.

INSTALLATION SUCCESSFUL!
------------------------------------------------
Lumos is now running in the background.
Check status: sudo systemctl status lumos
View logs:    sudo journalctl -u lumos -f

Ondanks enkele waarschuwingen in de aanmaak van de opdracht lumos-tui, wordt de installatie succesvol afgerond. De uitvoer van het installatiescript toont eveneens opdrachten om de status te controleren en de logboeken te bekijken. De status toont het volgende:

dany@pindabook:~/lumos$ sudo systemctl status lumos
lumos.service - Lumos Intelligent Auto-Brightness
    Loaded: loaded (/etc/systemd/system/lumos.service; enabled; preset: enabled)
    Active: active (running) since Sun 2026-01-25 16:09:35 CET; 2min 57s ago
Invocation: ac70354dcc96449688d0d63e7b51f0c8
  Main PID: 3622 (lumos)
     Tasks: 2 (limit: 9112)
    Memory: 232K (peak: 1.8M)
       CPU: 23ms
    CGroup: /system.slice/lumos.service
            └─3622 /usr/local/bin/lumos -i 60

jan 25 16:09:35 pindabook systemd[1]: Started lumos.service - Lumos Intelligent Auto-Brightness.

M.a.w. alles OK. En het logboek toont ons:

dany@pindabook:~/lumos$ sudo journalctl -u lumos -f
jan 25 16:09:35 pindabook systemd[1]: Started lumos.service - Lumos Intelligent Auto-Brightness.

Eveneens geen problemen. Stop het volgen van de logboekmeldingen met de sneltoets Ctrl+c.

Lumos gebruiken

Eigenlijk kan je Lumos enkel configureren, de rest gaat automatisch en op de achtergrond. Start het Lumos configuratie programma via de Programmastarter > Systeem > Lumos Control Configure Lumos Auto-Brightness.

Lumos

Je kunt Lumos het best testen (en configureren) door het Interval (s) op 5 in te stellen en iets voor de webcam te plaatsen (verduisteren). Het beeld wordt donkerder. Met een heldere lichtbron wordt het scherm helderder.

Dit zal niet altijd correct werken, waarover later meer.

Voor je experimenteert met de andere instellingen, zorg dat je de standaard waarden nog kunt herstellen (neem bijvoorbeeld een schermafbeelding).

Om een configuratie te blijven gebruiken, klik je op de knop .

Bij het sluiten van het Lumos configuratie venster, wordt het configuratieprogramma niet afgesloten, maar nestelt het zich in het systeemvak. Via het snelmenu van het Lumos systeemvak pictogram kan je het configuratievenster terug openen of helemaal afsluiten.

Systeemvak

Configuratie via de terminal

Daarvoor start je de volgende opdracht:

dany@pindabook:~/lumos$ lumos-tui

En je krijgt:


 Lumos TUI Control

 Use UP/DOWN to select, LEFT/RIGHT to adjust
 'S' to Save (Persist), 'Q' to Quit

   Mode (0=A,1=M)         : AUTO
   Manual Brightness      : 50
   Sensitivity            : 1.00
   Offset                 : 0
   Min Brightness         : 5
   Max Brightness         : 100
   Interval (s)           : 60
   Webcam                 : /dev/video0

De bediening gebeurt via sneltoetsen die je van het scherm kunt aflezen.

De instellingen worden opgeslagen in het bestand /etc/lumos.conf. Hoewel de GUI/TUI wordt aanbevolen, kun je dit bestand ook handmatig bewerken:

dany@pindabook:~/lumos$ sudo nano /etc/lumos.conf

# Lumos Configuration File

# Minimum brightness percentage (0-100)
min_brightness=5

# Maximum brightness percentage (0-100)
max_brightness=100

# Update interval in seconds
interval=60

# Brightness Offset (Default: 0)
brightness_offset=0

# Brightness Sensitivity (Default: 1.0)
sensitivity=1.00

# Mode (auto/manual)
mode=auto

# Manual Brightness Value (0-100)
manual_brightness=50

# Camera Device (e.g. /dev/video0)
camera_dev=/dev/video0

Sluit de nano editor af met de sneltoets Ctrl+x.

Na handmatige aanpassingen moet je de service opnieuw starten of een signaal verzenden, maar het gebruik van de GUI/TUI is eenvoudiger omdat deze de configuratie aanpassingen automatisch opnieuw laden.

Lichtmeter afzonderen

Nu gaan we de Lumos broncode gebruiken om een lichtmeter te bouwen. Dit is een vereenvoudiging van Lumos en volgt één kern principes van Linux: Kleine programma's voor één doel. Het principe van kleine programma's voor één doel is een ontwerpfilosofie die de nadruk legt op het maken van kleine, gespecialiseerde programma's die een specifieke taak of functie goed uitvoeren.

Daaruit volgt bijna automatisch een tweede Linux kern principe: De mogelijkheid om programma's aan elkaar te koppelen om complexe taken uit te voeren. In navolging van het principe van programma's met één doel is de mogelijkheid om programma's aan elkaar te koppelen om complexe taken uit te voeren een belangrijk principe van de Unix/Linux-filosofie. Het concept verwijst naar de praktijk waarbij de uitvoer van het ene programma als invoer voor een ander programma wordt gebruikt, waardoor een reeks programma's aan elkaar wordt gekoppeld om krachtigere en geavanceerdere functionaliteit te bereiken.

Lumos verwijderen

Eerst verwijderen we Lumos uit het systeem, zonder de broncode te verwijderen. Eerst stoppen we de achtergrond daemon:

dany@pindabook:~/lumos$ sudo systemctl stop lumos

En zorgen dat deze bij de volgende herstart niet terug automatisch geactiveerd wordt:

dany@pindabook:~/lumos$ sudo systemctl disable lumos
Removed '/etc/systemd/system/multi-user.target.wants/lumos.service'.

Daarna verwijderen we achtereenvolgens het opstartscript, de Lumos programmabestanden, het Programmastarter item en het configuratiebestand.

dany@pindabook:~/lumos$ sudo rm /etc/systemd/system/lumos.service
dany@pindabook:~/lumos$ sudo rm /usr/local/bin/lumos /usr/local/bin/lumos-tui /usr/local/bin/lumos-gui.py
dany@pindabook:~/lumos$ sudo rm /usr/share/applications/lumos-gui.desktop
dany@pindabook:~/lumos$ sudo rm /etc/lumos.conf

Als test herladen we de opstartprocedure van het systeem.

dany@pindabook:~/lumos$ sudo systemctl daemon-reload

Geen nieuw is goed niews. De map met de broncode verlaten we met:

dany@pindabook:~/lumos$ cd

Na het bekijken van de Lumos broncode, kwam ik al vlug tot de conclusie dat de kern van Lumos in het bronbestand main.c stond. Voor we dit bronbestand gaan aanpassen, maken we een reservekopie om op te werken:

dany@pindabook:~$ cp lumos/main.c .

En passen het broncode bestand aan met bijvoorbeeld de teksteditor nano:

dany@pindabook:~$ nano main.c  

Daarbij verwijderen we alle broncode die niets te maken heeft met het meten van de lichtintensiteit via de webcam. Dit houden we over:

* Lumos: Light Meter
* Author: Dany Pinoy
*         Extracted from Lumos project from Anıl Aras
* License: MIT
*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <linux/videodev2.h>

#define DEFAULT_CAMERA_DEV "/dev/video0"
#define WARMUP_FRAMES 5
#define WIDTH 640
#define HEIGHT 480

typedef struct {
   char camera_dev[64];
} Config;

Config config = {
   .camera_dev = DEFAULT_CAMERA_DEV
};

int verbose = 0;

int capture_luma() {
   int fd = open(config.camera_dev, O_RDWR);
   if (fd < 0) {
       if (verbose) perror("Camera open failed");
       return -1;
   }

   struct v4l2_format fmt = {0};
   fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
   fmt.fmt.pix.width = WIDTH;
   fmt.fmt.pix.height = HEIGHT;
   fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;

   if (ioctl(fd, VIDIOC_S_FMT, &fmt) == -1) {
       close(fd); return -1;
   }

   struct v4l2_requestbuffers req = {0};
   req.count = 1;
   req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
   req.memory = V4L2_MEMORY_MMAP;
   ioctl(fd, VIDIOC_REQBUFS, &req);

   struct v4l2_buffer buf = {0};
   buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
   buf.memory = V4L2_MEMORY_MMAP;
   buf.index = 0;
   ioctl(fd, VIDIOC_QUERYBUF, &buf);

   void *buffer_start = mmap(NULL, buf.length, PROT_READ | PROT_WRITE, MAP_SHARED, fd, buf.m.offset);
   if (buffer_start == MAP_FAILED) { close(fd); return -1; }

   enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
   ioctl(fd, VIDIOC_STREAMON, &type);

   long total_y = 0;
   int pixel_count = 0;

   for (int i = 0; i <= WARMUP_FRAMES; i++) {
       ioctl(fd, VIDIOC_QBUF, &buf);
       ioctl(fd, VIDIOC_DQBUF, &buf);

       if (i == WARMUP_FRAMES) {
           unsigned char *data = (unsigned char *)buffer_start;
           for (unsigned int j = 0; j < buf.bytesused; j += 20) {
               total_y += data[j];
               pixel_count++;
           }
       }
   }

   ioctl(fd, VIDIOC_STREAMOFF, &type);
   munmap(buffer_start, buf.length);
   close(fd);

   return (pixel_count == 0) ? 0 : (int)(total_y / pixel_count);
}

int main(int argc, char *argv[]) {
   int luma = capture_luma();
   printf("Brightness: %d\n", luma);
   return 0;
}

Nu we de broncode hebben aangepast, moeten we deze nog omzetten (compileren) naar een uitvoerbare opdracht. Deze informatie halen we terug uit de originele broncode uit het lumos/Makefile bestand. De opdracht om de aangepaste broncode te compileren naar de opdracht lightmeter wordt dan:

dany@pindabook:~$ gcc -O2 -Wall -o lightmeter main.c

Opnieuw is geen nieuws, goed nieuws. We testen onze op Lumos gebaseerde lichtmeter opdracht met:

dany@pindabook:~$ ./lightmeter  
Brightness: 99

De lichtmeter gebruiken in een toepassing

Om het resultaat van de lichtmeter vlotter in een script te kunnen gebruiken, verwijderen we alle overbodige uitvoer. We tonen dus enkel de berekende waarde. M.a.w. pas in het main.c broncode bestand de volgende regel:

   printf("Brightness: %d\n", luma);

aan naar

   printf("%d", luma);

Compileer en test de aangepaste lichtmeter:

dany@pindabook:~$ gcc -O2 -Wall -o lightmeter main.c
dany@pindabook:~$ ./lightmeter  
81dany@pindabook:~$  

Je merkt dat vlak na de helderheidswaarde de groene prompt verschijnt. Dit is te wijten aan het ontbreken van een regelterugloop (\n in de broncode). Dit is op zich geen probleem, wel verwarrend. Druk op de sneltoets Ctrl+c om de promptpositie te herstellen.

Om de lichtmeter opdracht beter bereikbaar te maken, verplaats je deze naar een map van waaruit de terminal rechtstreeks opdrachten kan uitvoeren:

dany@pindabook:~$ sudo mv lightmeter /usr/local/bin/
[sudo] wachtwoord voor dany:  

Misschien heb je het al gemerkt, de lichtmeter waarden zijn niet stabiel en liggen soms hoger als het donker wordt. Dit is te wijten aan een automatische belichtingsconfiguratie voor foto's en video, en deze functie is meestal standaard geactiveerd.

De werking van video op Linux wordt verzorgt door Video4Linux (V4L). Videoapparatuur zoals webcams kan je configureren via V4L. Installeer daarvoor het volgende pakket:

dany@pindabook:~$ sudo apt install v4l-utils
[sudo] wachtwoord voor dany:  
Installeren:                               
 v4l-utils

Installeren van vereisten:
 libv4l2rds0t64

Samenvatting:
 Opwaarderen: 0, Installeren: 2, Verwijderen: 0, Niet opwaarderen: 0
 Downloadgrootte: 853 kB
 Benodigde ruimte: 2.941 kB / 84,6 GB beschikbaar

Doorgaan? [J/n]  
Ophalen:1 http://deb.debian.org/debian trixie/main amd64 libv4l2rds0t64 amd64 1.30.1-1 [88,2 kB]
Ophalen:2 http://deb.debian.org/debian trixie/main amd64 v4l-utils amd64 1.30.1-1 [765 kB]
853 kB opgehaald in 0s (9.028 kB/s)
Voorheen niet geselecteerd pakket libv4l2rds0t64:amd64 wordt geselecteerd.
(Database wordt ingelezen ... 206701 bestanden en mappen momenteel geïnstalleerd.)
Uitpakken van .../libv4l2rds0t64_1.30.1-1_amd64.deb wordt voorbereid...
Bezig met uitpakken van libv4l2rds0t64:amd64 (1.30.1-1) ...
Voorheen niet geselecteerd pakket v4l-utils wordt geselecteerd.
Uitpakken van .../v4l-utils_1.30.1-1_amd64.deb wordt voorbereid...
Bezig met uitpakken van v4l-utils (1.30.1-1) ...
Instellen van libv4l2rds0t64:amd64 (1.30.1-1) ...
Instellen van v4l-utils (1.30.1-1) ...
Bezig met afhandelen van triggers voor libc-bin (2.41-12+deb13u1) ...
Bezig met afhandelen van triggers voor man-db (2.13.1-1) ...

Met de volgende opdracht achterhaal je welke apparaten (devices) door V4L bediend worden:

dany@pindabook:~$ v4l2-ctl --list-devices
Integrated Camera: Integrated C (usb-0000:00:14.0-6):
       /dev/video0
       /dev/video1
       /dev/media0

Mijn laptop heeft dus één camera die door V4L opgedeeld is in drie apparaten. Proefondervindelijk kom je snel te weten welk V4L apparaat kan gebruikt worden voor de lichtmeting (zie broncode). Standaard is dit /dev/video0. Daarna kan je van het gebruikte V4L apparaat de eigenschappen opvragen:

dany@pindabook:~$ v4l2-ctl -d /dev/video0 -L

User Controls

                    brightness 0x00980900 (int)    : min=-64 max=64 step=1 default=0 value=0
                      contrast 0x00980901 (int)    : min=0 max=100 step=1 default=50 value=50
                    saturation 0x00980902 (int)    : min=0 max=100 step=1 default=64 value=64
                           hue 0x00980903 (int)    : min=-180 max=180 step=1 default=0 value=0
                         gamma 0x00980910 (int)    : min=100 max=500 step=1 default=300 value=300
                          gain 0x00980913 (int)    : min=16 max=255 step=1 default=16 value=16
          power_line_frequency 0x00980918 (menu)   : min=0 max=2 default=1 value=1 (50 Hz)
                               0: Disabled
                               1: 50 Hz
                               2: 60 Hz
                     sharpness 0x0098091b (int)    : min=0 max=100 step=1 default=50 value=50
        backlight_compensation 0x0098091c (int)    : min=0 max=1 step=1 default=0 value=0

Camera Controls

                 auto_exposure 0x009a0901 (menu)   : min=0 max=3 default=3 value=3 (Aperture Priority Mode)
                               1: Manual Mode
                               3: Aperture Priority Mode
        exposure_time_absolute 0x009a0902 (int)    : min=50 max=10000 step=1 default=166 value=166 flags=inactive
    exposure_dynamic_framerate 0x009a0903 (bool)   : default=0 value=0
                  pan_absolute 0x009a0908 (int)    : min=-57600 max=57600 step=3600 default=0 value=0
                 tilt_absolute 0x009a0909 (int)    : min=-43200 max=43200 step=3600 default=0 value=0
                 zoom_absolute 0x009a090d (int)    : min=0 max=3 step=1 default=0 value=0

Jammer genoeg is dit niet voor alle video apparatuur hetzelfde, de naamgeving en functieomvang hangt af van het type en de stuurprogramma's. Wat je wel bij elke eigenschap in de uitvoer ziet zijn de minimum, maximum, stapgrootte, standaard waarde en effectieve waarde. Laten we veronderstellen dat de fabrikant (stuurprogramma ontwikkelaar) verstandige standaardwaarden heeft gekozen. Wat we voor de lichtmeter wel willen uitschakelen zijn alle auto controllers. Mijn webcam heeft er maar één die in aanmerking komt: auto_exposure. Ook andere controllers kunnen onze lichtmeting storen, zoals bijvoorbeeld backlight_compensation, maar deze staat bij mij standaard uitgeschakeld (0). Nog andere controllers zoals white_balance_temperature_auto (niet vermeld en dus niet mogelijk met mijn laptop webcam) kunnen storen. De automatische camera belichting schakel ik voor mijn laptop webcam uit met de volgende opdracht:

dany@pindabook:~$ v4l2-ctl -d /dev/video0 --set-ctrl=auto_exposure=1

Voer enkele lichtmetingen na elkaar uit en controleer of je stabieler waarden krijgt. M.a.w. stel proefondervindelijk vast wat het beste werkt.

Met het volgende script zorg ik voor een zelflerende helderheidsaanpassing van mijn laptopscherm. Onze lichtmeter wordt gebruikt om het omgevingslicht te meten en de maximum gemeten lichtsterkte op te slaan. De schermhelderheid mag daarbij variëren tussen 10% en 90% van de maximaal instelbare helderheid. Daarenboven wordt de schermhelderheid in kleine onzichtbare stappen aangepast.

Onderstaande script werkt enkel in KDE 6. Je kunt het script aanpassen om via het Linux systeem de schermhelderheid aan te passen, zodat het ook in niet KDE 6 omgevingen werkt. De benodigde regels heb ik met behulp van commentaar uitgeschakeld. Je moet dan echter ook de typische KDE 6 en daaruit volgende regels deactiveren. Een mooie oefening.

Indien je gebruik maakt van de helderheidsregeling via het Linux systeem, is de grafische KDE omgeving niet op de hoogte van de helderheidswijziging en geven deze dus foutieve waarden.

#!/bin/bash
# brightness.sh

# controleer en pas aan met: v4l2-ctl -d /dev/video0 -L
v4l2-ctl -d /dev/video0 --set-ctrl=auto_exposure=1

minbacklight="10" # in percent
maxbacklight="90" # in percent

# Controleer of het script al gestart is!
aantal=$(ps aux | grep -v "grep" | grep "$0" | wc -l)
# Bij een eerste start wordt het script gestart,
# bij een tweede start wordt het draaiende script afgesloten
echo $0
echo $aantal
if [ $aantal -gt 2 ]; then # Sluit het draaiende script af
 proces=$(ps aux | grep -v "grep" | grep "$0" | awk '{print $2}')
 kill $proces
 exit
fi

persistent="$HOME/.brightness"
if [ ! -f "$persistent" ]; then
 echo "$persistent wordt aangemaakt."
 echo "maxlux=0" > "$persistent"
fi

#sysbacklight="/sys/class/backlight/intel_backlight"
#sysmaxbacklight=$(cat $sysbacklight/max_brightness)
#minbacklight=$(awk "BEGIN {printf \"%.0f\", $sysmaxbacklight * $minbacklight / 100}")
#echo Minimale instelbare helderheid: $minbacklight
#maxbacklight=$(awk "BEGIN {printf \"%.0f\", $sysmaxbacklight * $maxbacklight / 100}")
#echo Maximale instelbare helderheid: $maxbacklight

sysmaxbacklight=$(qdbus6 org.kde.Solid.PowerManagement /org/kde/Solid/PowerManagement/Actions/BrightnessControl org.kde.Solid.PowerManagement.Actions.BrightnessControl.brightnessMax)
minbacklight=$(awk "BEGIN {printf \"%.0f\", $sysmaxbacklight * $minbacklight / 100}")
echo Minimale instelbare helderheid: $minbacklight
maxbacklight=$(awk "BEGIN {printf \"%.0f\", $sysmaxbacklight * $maxbacklight / 100}")
echo Maximale instelbare helderheid: $maxbacklight
stepsbacklight=$(qdbus6 org.kde.Solid.PowerManagement /org/kde/Solid/PowerManagement/Actions/BrightnessControl org.kde.Solid.PowerManagement.Actions.BrightnessControl.brightnessSteps)
stepsbacklight=$((stepsbacklight * 5))
#stepsbacklight=1
echo Aanpasstappen instelbare helderheid: $stepsbacklight

while :
do
 # Haal het omgevingslicht op
 lux=$(lightmeter)
 if [ $? == 0 ]; then # Ophalen van meting gelukt en kan dus verwerkt worden
   echo "Omgevingslicht: $lux"
   source "$persistent"
   echo Maximaal gemeten omgevingslicht: $maxlux
   if (( lux > maxlux )); then
     echo "maxlux=$lux" > "$persistent"
     maxlux=$lux
   fi

   rangebrightness=$(awk "BEGIN {printf \"%.0f\", $maxbacklight - $minbacklight}")
   echo Bereik instelbare helderheid: $rangebrightness

   rellux=$(awk "BEGIN {printf \"%.2f\", $lux / $maxlux}")
   echo Relatief omgevingslicht: $rellux
   helderheid=$(awk "BEGIN {printf \"%.0f\", $minbacklight + $rellux * $rangebrightness}")

   # Huidige helderheid
#    huidige=$(cat $sysbacklight/brightness)
   huidige=$(qdbus6 org.kde.Solid.PowerManagement /org/kde/Solid/PowerManagement/Actions/BrightnessControl org.kde.Solid.PowerManagement.Actions.BrightnessControl.brightness)

   # Helderheid geleidelijk aanpassen
   echo "Helderheid aanpassen van $huidige naar $helderheid"
   if [ ${huidige%.*} -eq ${helderheid%.*} ] && [ ${huidige#*.} \< ${helderheid#*.} ] || [ ${huidige%.*} -lt ${helderheid%.*} ]; then
     for i in $( LANG=en_US seq $huidige $stepsbacklight $helderheid ); do
       echo verhogen: $i
#        echo $i > /sys/class/backlight/intel_backlight/brightness
       qdbus6 org.kde.Solid.PowerManagement /org/kde/Solid/PowerManagement/Actions/BrightnessControl org.kde.Solid.PowerManagement.Actions.BrightnessControl.setBrightness $i
       sleep 1
     done
   else
     for i in $( LANG=en_US seq $huidige -$stepsbacklight $helderheid ); do
       echo verlagen: $i
#        echo $i > /sys/class/backlight/intel_backlight/brightness
       qdbus6 org.kde.Solid.PowerManagement /org/kde/Solid/PowerManagement/Actions/BrightnessControl org.kde.Solid.PowerManagement.Actions.BrightnessControl.setBrightness $i
       sleep 1
     done
   fi
 fi
 # Wacht 1 minuut
 sleep 60
done

Start (test) het script met de volgende opdracht:

dany@pindabook:~$ bash brightness.sh  
brightness.sh
2
/home/dany/.brightness wordt aangemaakt.
Minimale instelbare helderheid: 1000
Maximale instelbare helderheid: 9000
Aanpasstappen instelbare helderheid: 100
Omgevingslicht: 30
Maximaal gemeten omgevingslicht: 0
Bereik instelbare helderheid: 8000
Relatief omgevingslicht: 1.00
Helderheid aanpassen van 7000 naar 9000
verhogen: 7000
verhogen: 7100
verhogen: 7200
verhogen: 7300
verhogen: 7400
verhogen: 7500
verhogen: 7600
verhogen: 7700
verhogen: 7800
verhogen: 7900
verhogen: 8000
verhogen: 8100
verhogen: 8200
verhogen: 8300
verhogen: 8400
verhogen: 8500
verhogen: 8600
verhogen: 8700
verhogen: 8800
verhogen: 8900
verhogen: 9000
Omgevingslicht: 30
Maximaal gemeten omgevingslicht: 30
Bereik instelbare helderheid: 8000
Relatief omgevingslicht: 1.00
Helderheid aanpassen van 9000 naar 9000
verlagen: 9000

Het script zit nog in een lerende fase (bepalen van het maximale omgevingslicht) en zal dus een schermhelderheid van 90% instellen. Als je de test in een lichtrijke omgeving uitvoert is dit wat je wil, doe je dit in een donkere omgeving echter niet. M.a.w. in de lerende fase moet je de ideale omstandigheden creëren (lichtrijk).

Breek het script af met de sneltoets Ctrl+c.

Tijdens de helderheidsaanpassing van het scherm krijg je de hinderende helderheidsmelding (On Screen Display of OSD) van KDE op het scherm. Dit schakel je uit door in de Systeeminstellingen in de groep Werkruimte op de pagina Algemeen gedrag de optie Visuele terugkoppeling voor statuswijzigingen tonen uit te schakelen. Opgelet: dit schakelt ook de melding voor volumeaanpassingen uit.

Tenslotte kan je het script automatisch bij het opstarten van KDE starten door het via de Systeeminstellingen in de groep Systeem op de pagina Autostart via het uitklapmenu + Nieuwe toevoegen met de opdracht + Aanmeldscript... het script te selecteren als aanmeldscript.

Autostart

Als het script automatisch werd gestart, kan je het stoppen door het script manueel in een terminal te starten. Het script controleert namelijk bij het starten of het reeds draait en breekt alle brightness.sh scripts af. Dus pas bij de volgende manuele of automatische start van het script wordt het weer actief.

En verder

Je kunt het script verder aanpassen, aanvullen met bijvoorbeeld stuurparameters om een leermodus te activeren, dus zonder schermhelderheidsaanpassingen. Experimenteren met snelle bruuske helderheidswijzigingen. Starten en stoppen via een systemd service. En/of dit gebruiken voor een compleet nieuwe toepassing. Dit is tenslotte Open Source.

Opruimen

Voor je iets verwijderd, zorg je dat het script niet meer werkt. Dit kan door manueel (in een terminal) het brightness.sh script te starten.

dany@pindabook:~$ bash brightness.sh  
brightness.sh
3
Beëindigd

Daarna verwijder je alle lichtmeter en helderheidsregelende onderdelen met de volgende verwijderopdracht:

dany@pindabook:~$ sudo rm -r lumos/ main.c /usr/local/bin/lightmeter .brightness  
[sudo] wachtwoord voor dany:  

Verwijder daarna de geïnstalleerde hulppakketten:

dany@pindabook:~$ sudo apt purge libncurses-dev python3-pyqt6 v4l-utils
De volgende pakketten zijn automatisch geïnstalleerd en zijn niet langer nodig:
 libqt6test6  libv4l2rds0t64  python3-pyqt6.sip
Gebruik 'sudo apt autoremove' om ze te verwijderen.

VERWIJDEREN:
 libncurses-dev*  python3-pyqt6*  v4l-utils*

Samenvatting:
 Opwaarderen: 0, Installeren: 0, Verwijderen: 3, Niet opwaarderen: 0
 Vrijgemaakte ruimte: 23,2 MB

Doorgaan? [J/n]  
(Database wordt ingelezen ... 206732 bestanden en mappen momenteel geïnstalleerd.)
libncurses-dev:amd64 (6.5+20250216-2) wordt verwijderd ...
python3-pyqt6 (6.9.0-2) wordt verwijderd ...
v4l-utils (1.30.1-1) wordt verwijderd ...
Bezig met afhandelen van triggers voor man-db (2.13.1-1) ...

Om ook de niet meer gebruikte afhankelijke pakketten te verwijderen, voer je de volgende opdracht uit:

dany@pindabook:~$ sudo apt autoremove
VERWIJDEREN:                               
 libqt6test6  libv4l2rds0t64  python3-pyqt6.sip

Samenvatting:
 Opwaarderen: 0, Installeren: 0, Verwijderen: 3, Niet opwaarderen: 0
 Vrijgemaakte ruimte: 957 kB

Doorgaan? [J/n]  
(Database wordt ingelezen ... 206593 bestanden en mappen momenteel geïnstalleerd.)
libqt6test6:amd64 (6.8.2+dfsg-9+deb13u1) wordt verwijderd ...
libv4l2rds0t64:amd64 (1.30.1-1) wordt verwijderd ...
python3-pyqt6.sip (13.10.0-1+b1) wordt verwijderd ...
Bezig met afhandelen van triggers voor libc-bin (2.41-12+deb13u1) ...

Vergeet ook niet de aanpassingen in de Systeeminstellingen te herstellen. Schakel bij Algemeen gedrag de optie Visuele terugkoppeling voor statuswijzigingen tonen terug in en verwijder het aanmeldscript brightness.sh bij Autostart.