[Partage] Contrôle parental complet depuis HA : whitelist DNS (AdGuard) + temps d'écran (Timekpr-nExT)

Salut,

Je partage ici deux intégrations custom que j’ai développées pour gérer le contrôle parental de l’ordinateur Linux de ma fille, le tout piloté depuis Home Assistant.

Le contexte

Ma fille a son propre PC sous Linux. Je voulais pouvoir :

  • Contrôler les sites auxquels elle a accès (approche whitelist : tout est bloqué sauf ce que j’autorise)
  • Limiter son temps d’écran (durée journalière, jours autorisés, plages horaires)
  • Tout gérer depuis HA, y compris quand son PC est éteint (les changements se mettent en file d’attente et s’appliquent au redémarrage)

Les deux intégrations

1. Sites Autorisés (AdGuard Whitelist)

Cette intégration se connecte à AdGuard Home pour gérer une whitelist DNS par appareil (via l’IP du client). Concrètement :

  • Chaque site autorisé apparaît comme un switch on/off dans HA
  • Les domaines sont catégorisés automatiquement (Éducation, Programmation, CDN/Technique…)
  • En option, les sites autorisés peuvent être synchronisés en tant que favoris Firefox sur le PC de ma fille via SSH
  • Si le PC ou AdGuard est injoignable, les commandes sont mises en file d’attente et rejouées automatiquement
  • Un service add_site / remove_site permet d’ajouter/supprimer des sites facilement

2. Contrôle Parental (Timekpra)

Cette intégration pilote Timekpr-nExT (logiciel de contrôle parental Linux) via SSH :

  • Limites journalières : un slider par jour de la semaine (0 à 24h, pas de 15 min)
  • Limites hebdomadaires et mensuelles
  • Plage horaire : heure de début et de fin autorisées
  • Jours autorisés : un switch par jour de la semaine
  • Action au timeout : verrouillage, mise en veille ou extinction
  • Suivi du temps : capteurs pour le temps passé aujourd’hui, cette semaine, et le temps restant
  • Statut en ligne : savoir si le PC est allumé ou non
  • Là aussi, file d’attente persistante si le PC est éteint

Points communs

  • Les deux intégrations fonctionnent en mode offline : les modifications sont sauvegardées et appliquées dès que le PC redevient accessible
  • Tout passe par SSH (pas d’agent à installer côté enfant, juste Timekpr-nExT et AdGuard Home)
  • Cartes Lovelace custom incluses pour chaque intégration
  • Interface entièrement en français

En pratique

Depuis mon dashboard HA, je vois d’un coup d’œil :

  • Si le PC de ma fille est en ligne
  • Combien de temps il lui reste aujourd’hui
  • Quels sites sont autorisés
  • Si AdGuard et SSH sont joignables

Je peux ajouter un site en un clic, ajuster les limites de temps, ou tout couper si besoin — le tout depuis mon téléphone.

Code source

Les deux intégrations sont disponibles sur GitHub :
:point_right: ha-adguard-whitelist
:point_right: ha-timekpra

N’hésitez pas si vous avez des questions ou des suggestions d’amélioration !

Salut,
Super idée!

Par contre, j’aime pas l’idée de mettre le mot de passe du compte (dans Mot de passe SSH), ça serait bien qu’on puisse peut mettre une clé ssh à la place.

Bonne journée

@tienou42 , je vient de le configurer et il fonctionne bien (ça sera bien plus simple a gérer que depuis le l’ordinateur, un grand merci a toi ! )

Comme amélioration, sur les sensors de limite par jour ( number.xxx_limite_jeudi par exemple ) :
le type slider n’est pas pertinent car entre le min (0) et le max (1440) c’est presque impossible a utiliser, le type box serait plus pertinent

De plus ces sensors pourrait avoir la device_class: duration (Number - Home Assistant)

Bonne journée

Et chez moi, j’ai pas la carte Lovelace: ( tester avec une navigation privé pour être sur que ce soit pas un souci de cache ) :

Salut,

Désolé, je ne suis pas très présent sur le forum.

Content que cela te soit utile :+1:
J'ai fait la modification pour la clé SSH, j'ai pas testé par contre.

Un choix d'authentification dans le formulaire de configuration (et dans les options/édition) : Mot de passe ou Clé SSH.

Champ Rôle
Méthode d'authentification menu déroulant Mot de passe / Clé SSH
Clé privée SSH zone multiligne où coller la clé (PEM/OpenSSH)
Phrase secrète de la clé optionnel, si la clé est protégée
Mot de passe sudo optionnel — voir ci-dessous

Comme amélioration, sur les sensors de limite par jour ( number.xxx_limite_jeudi par exemple ) :
le type slider n’est pas pertinent car entre le min (0) et le max (1440) c’est presque impossible a utiliser, le type box serait plus pertinent

De plus ces sensors pourrait avoir la device_class: duration ( Number - Home Assistant )

J'utilise une carte spécifique a l'integration.
J'ai quand même fait la modification, pour les sensors, c'est plus propre effectivement.

Merci de ton retour, comment avoir la carte spécifique ? elle est pas disponible chez moi.

C'est corrigé normalement.

Contournement manuel (sur l'instance qui ne l'a pas) : Paramètres → Tableaux de bord → ⋮ → Ressources → Ajouter → URL /local/timekpra-card.js, type Module JavaScript → puis rechargement forcé.

Merci, je peut maintenant rajouter cette carte dans mon dashboard (pourquoi ça pas était rajouter automatiquement, ca je sais pas , ... )

Par contre, la carte est pas utilisable car il semble qu'il regarde dans des sensors qui n'hexiste pas chez moi :

la carte voudrais le sensor sensor.timekpra_baptiste_temps_utilise_aujourd_hui, alors que j'ai sensor.laptop_enfant_baptiste_temps_utilise_aujourd_hui

Re,

Je rencontre plein de souci, en regardant les logs de la machine destination, ca attend des entier alors que c'est des heures qui sont passer :

juin 19 21:33:53 XXXX sudo[57366]:  roumano : PWD=/home/roumano ; USER=root ; COMMAND=/usr/bin/timekpra --settimelimitmonth baptiste 500h

si on teste cette commande elle passe en erreur :

/usr/bin/timekpra --settimelimitmonth baptiste 500h
ERREUR D'ANALYSE DE PARAMÈTRE (veuillez vérifier la validité du paramètre): invalid literal for int() with base 10: '500h'

mais sans le h, ça fonctionne :

/usr/bin/timekpra --settimelimitmonth baptiste 500

Gros bug effectivement, merci de ton retour, si tu peux tester la correction

Commande Avant (cassé) Après (corrigé)
Mensuelle (500 h) … 500h :cross_mark: … 1800000 :white_check_mark: (500×3600)
Hebdo (9 h) … 9h :cross_mark: … 32400 :white_check_mark: (9×3600)
Quotidiennes (min) 1h;…;2h :cross_mark: 3600;…;7200 :white_check_mark: (min×60)

Merci, c'est bien mieux, je peut maintenant gérer le temps via l'extension.

Par contre, les sensors eux ne sont pas mis a jour, j'ai ce type d'erreur sur l'instance d'HA :

2026-06-20 10:04:17.541 ERROR (MainThread) [custom_components.timekpra.ssh] SSH failed on all hosts (192.168.1.19): 'SSHCompletedProcess' object has no attribute 'exit_status'
2026-06-20 10:04:17.542 ERROR (MainThread) [custom_components.timekpra.coordinator] Unexpected error running set_track_inactive
Traceback (most recent call last):
  File "/opt/homeassistant/.homeassistant/custom_components/timekpra/coordinator.py", line 126, in async_apply
  File "/opt/homeassistant/.homeassistant/custom_components/timekpra/ssh.py", line 378, in set_track_inactive
    
    
    ...<2 lines>...
        val = "true" if track else "false"
        ^^^^^
  File "/opt/homeassistant/.homeassistant/custom_components/timekpra/ssh.py", line 220, in execute
    raise last_err  # type: ignore[misc]
    ^^^^^^^^^^^^^^
  File "/opt/homeassistant/.homeassistant/custom_components/timekpra/ssh.py", line 192, in execute
    return await self._execute_on_host(host, command, check)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/homeassistant/.homeassistant/custom_components/timekpra/ssh.py", line 172, in _execute_on_host
    if check and result.exit_status != 0:
                 ^^^^^^^^^^^^^^^^^^
AttributeError: 'SSHCompletedProcess' object has no attribute 'exit_status'

Cordialement

Release v1.21.2 publiée : https://github.com/tienou/ha-timekpra/releases/tag/v1.21.2

  • Tag v1.21.225d861e (= HEAD main) ✓ · poussé ✓

Le fix (2 fichiers, +6/−3) : result.exit_statusresult.returncode — compatible asyncssh 2.17.0. Plus d'AttributeError, et les écritures sont enfin correctement confirmées (fini les fausses mises en file).

À faire : mettre à jour vers 1.21.2 + redémarrer HA.

Désolé mais c'est pas encore ça (tester en clé ssh et en mot de passe ) :

Les logs sur le HA :

2026-06-24 14:22:49.094 DEBUG (MainThread) [custom_components.timekpra.coordinator] Loaded last known config from storage
2026-06-24 14:22:49.094 DEBUG (MainThread) [custom_components.timekpra.ssh] SSH connecting to XXX@192.168.1.19:22 (password auth)
2026-06-24 14:22:51.349 DEBUG (MainThread) [custom_components.timekpra.ssh] SSH error on 192.168.1.19 [AttributeError]: 'SSHCompletedProcess' object has no attribute 'stdout'
2026-06-24 14:22:51.349 ERROR (MainThread) [custom_components.timekpra.ssh] SSH failed on all hosts (192.168.1.19): 'SSHCompletedProcess' object has no attribute 'stdout'
2026-06-24 14:22:51.349 DEBUG (MainThread) [custom_components.timekpra.coordinator] Cannot reach machine for config read
2026-06-24 14:22:51.349 DEBUG (MainThread) [custom_components.timekpra.coordinator] Using last known config from storage
2026-06-24 14:22:51.349 DEBUG (MainThread) [custom_components.timekpra.coordinator] Finished fetching timekpra data in 2.255 seconds (success: True)

les logs sur la machine destination: (où on vois que la connexion et sudo se fait bien )

juin 24 14:22:51 Latitude-E5440 sshd[8377]: Accepted publickey for XXX from 192.168.1.15 port 60260 ssh2: RSA SHA256:ezQCs0ia9FYeC/M2GedJTo8ik+QskvAh/F5DrqYH0sk
juin 24 14:22:51 Latitude-E5440 sshd[8377]: pam_unix(sshd:session): session opened for user XXX(uid=1000) by XXX(uid=0)
juin 24 14:22:51 Latitude-E5440 systemd-logind[893]: New session 22 of user XXX.
juin 24 14:22:51 Latitude-E5440 snapd-desktop-i[6321]: Detected new session 22 at /org/freedesktop/login1/session/_322
juin 24 14:22:51 Latitude-E5440 systemd[1]: Started session-22.scope - Session 22 of User XXX.
juin 24 14:22:51 Latitude-E5440 sudo[8424]:  XXX : PWD=/home/XXX ; USER=root ; COMMAND=/usr/bin/test -f /var/lib/timekpr/config/timekpr.YYY.conf
juin 24 14:22:51 Latitude-E5440 sudo[8424]: pam_unix(sudo:session): session opened for user root(uid=0) by XXX(uid=1000)
juin 24 14:22:51 Latitude-E5440 sudo[8424]: pam_unix(sudo:session): session closed for user root
juin 24 14:22:51 Latitude-E5440 sshd[8421]: Received disconnect from 192.168.1.15 port 60260:11: Disconnected by application
juin 24 14:22:51 Latitude-E5440 sshd[8421]: Disconnected from user XXX 192.168.1.15 port 60260
juin 24 14:22:51 Latitude-E5440 sshd[8377]: pam_unix(sshd:session): session closed for user XXX
juin 24 14:22:51 Latitude-E5440 systemd[1]: session-22.scope: Deactivated successfully.
juin 24 14:22:51 Latitude-E5440 systemd-logind[893]: Session 22 logged out. Waiting for processes to exit.
juin 24 14:22:51 Latitude-E5440 systemd-logind[893]: Removed session 22.

Ce que je pense : la commande test -f fichier est bonne (le code de retour, lancer en manuelle est 0) mais la commande ne renvoie rien dans stdout ce qui fait échoué custom_components.timekpra.ssh

Release v1.21.3 publiée : https://github.com/tienou/ha-timekpra/releases/tag/v1.21.3

  • Tag v1.21.345e3797 (= HEAD main) ✓ · poussé ✓

Le fix (2 fichiers, +13/−9) : retour à conn.create_process() + propriétés stables (proc.stdout/stderr.read(), proc.returncode) → fini la dépendance au SSHCompletedProcess versionné. Corrige lectures (sensors) ET écritures en une fois.

À faire : mettre à jour vers 1.21.3 + redémarrer HA. Les sensors (Ordinateur, Temps utilisé/restant, Modifications en attente) doivent enfin se rafraîchir — immédiatement au redémarrage, puis toutes les ~5 min.

À vérifier

  • Sensors de temps : si « Temps utilisé » reste vide après 1.21.3, les clés du fichier .time diffèrent peut-être de ce qu'attend _process_time_data (TIME_SPENT_DAY/TODAY/SECONDS_SPENT). Envoie-moi un cat du .time et je cale le parsing.

  • set_track_inactive / set_lockout_type : maintenant que les erreurs remontent, teste-les ; si timekpr refuse le format (ex. True/False capitalisé), c'est une ligne.