Documentation / Résolution des problèmes / L’appareil ne diffuse qu’une ou certaines campagnes

L’appareil ne diffuse qu’une ou certaines campagnes

Présentation et repères

L’écran ne diffuse qu’une ou quelques campagnes, alors que la fiche de l’appareil, sous Campagnes publiées, en affiche davantage. Le redémarrage n’a rien changé. Ce guide explique comment vérifier les paramètres, comparer les listes de lecture et identifier les médias susceptibles de bloquer une mise à jour des contenus.

Liste de lecture désigne la liste des campagnes et de leurs règles de diffusion. Si le lecteur ne peut pas préparer un média requis par une nouvelle liste, il peut continuer à utiliser la précédente. La planification, le ciblage des campagnes, la connectivité et l’espace de stockage sont d’autres causes possibles.

Vérifications et résolution des problèmes

Diagnostiquez le problème avant toute modification. Les étapes 1 à 6 ne font que vérifier l’état actuel. L’étape 7 modifie la campagne dans le portail ; l’étape 8 interrompt brièvement la diffusion et modifie un fichier. Ne supprimez pas en masse les listes de lecture, les médias ou la base de données.

Procédure de diagnostic et de réparation

  1. Vérifiez les campagnes dans le portail.

    Ouvrez la fiche de l’appareil concerné et l’onglet Campagnes publiées. Pour les campagnes absentes, vérifiez qu’elles ciblent cet appareil, sont actives et que leurs dates et conditions de diffusion, jours et heures compris, sont valides. Comparez-les à l’heure réelle de l’appareil à l’étape 3.

    Une campagne non prévue à cet instant n’est pas nécessairement défectueuse. Si elle devrait être diffusée et que le redémarrage n’a rien changé, poursuivez. Consultez aussi les guides sur Campagnes et Appareils.

  2. Ouvrez la console à distance.

    L’appareil doit être en ligne et communiquer avec le serveur. La console à distance nécessite le rôle Administrateur du serveur ou supérieur. Ouvrez-la comme indiqué dans le guide Console à distance. Collez la commande dans le champ de saisie et envoyez-la avec ✓. Collez chaque bloc multiligne en entier, y compris la dernière ligne PY.

    Un aperçu à distance de l’écran ne donne pas accès à la console. Si l’appareil est hors ligne, suivez d’abord le guide Vérification de la connectivité de l’appareil. Si votre rôle ne donne pas accès, demandez à un administrateur habilité d’effectuer ces opérations. Voir Utilisateurs et autorisations.

    Les commandes ci-dessous concernent les lecteurs Linux utilisant le service device-runtime.service et le répertoire de travail /storage. Les blocs Python nécessitent Python 3 ; le test d’URL nécessite curl. Si la console signale qu’une commande, un service ou un chemin n’existe pas, ne modifiez aucun fichier. Contactez l’assistance.
  3. Vérifiez l’heure, l’espace disque et le service du lecteur.

    Commande à copier :

    date
    df -h / /storage
    systemctl is-active device-runtime.service
    ls -lh --time-style=long-iso /storage/playlist /storage/playlist_new
    
    Ce que vous voyezSignification et suite à donner
    Date et heureComparez-les à l’heure locale actuelle et au fuseau horaire. Une heure incorrecte peut affecter la sélection des campagnes et la connectivité.
    Espace libre dans la colonne AvailSi le stockage est plein, suivez le guide Espace disque insuffisant. Vérifiez aussi la partition montée sur /storage.
    activeLe service fonctionne. Cela ne confirme pas encore une diffusion correcte ni une mise à jour réussie.
    inactive, failed ou fichiers manquantsConsultez les journaux à l’étape 5. N’utilisez pas la réparation temporaire avant d’avoir vérifié l’installation et la cause.

    /storage/playlist contient la liste de lecture actuellement acceptée par le lecteur. /storage/playlist_new contient la nouvelle liste reçue, dont le lecteur prépare les médias avant activation. Un horodatage plus récent ou une taille différente est un indice utile, mais ne prouve pas à lui seul une anomalie. Les fichiers peuvent différer temporairement pendant un téléchargement normal.

  4. Comparez les campagnes des deux listes de lecture.

    Le bloc suivant lit les deux fichiers et affiche l’ID numérique de l’appareil, le nombre de campagnes, leurs ID, noms et dates de validité. Il ne modifie rien. Notez l’ID numérique de l’appareil : l’en-tête de la console peut afficher un autre identifiant, à ne pas utiliser ensuite dans DEVICE_ID.

    Commande à copier :

    python3 - <<'PY'
    import json
    for path in ['/storage/playlist', '/storage/playlist_new']:
        print('\nFICHIER :', path)
        try:
            with open(path) as f:
                data = json.load(f)
            print('Appareil :', data.get('deviceId'))
            campaigns = data.get('campaigns', [])
            print('Nombre de campagnes :', len(campaigns))
            for c in campaigns:
                print(c.get('campaignId'), c.get('nameCampaign'),
                      'du :', c.get('start'), 'au :', c.get('end'))
        except Exception as e:
            print('ERREUR :', e)
    PY
    

    Si la nouvelle liste contient les campagnes attendues mais que la liste actuelle n’en contient qu’une ancienne sélection, recherchez une erreur de préparation à l’étape suivante. Si elles manquent aussi dans le nouveau fichier, vérifiez les paramètres et la réception des mises à jour du portail. Une erreur d’analyse JSON peut signaler un fichier incomplet ou endommagé ; ne l’écrasez pas manuellement sans vérifications supplémentaires.

  5. Trouvez l’erreur de téléchargement et vérifiez la réponse du serveur.

    Affichez les 120 dernières entrées du journal du service des 20 dernières minutes. Recherchez les erreurs répétées, l’URL du média et son ID. Si seule la fin d’une erreur apparaît, augmentez -n 120 ou élargissez la période.

    Commande à copier :

    sudo journalctl -u device-runtime.service --since "20 minutes ago" --no-pager -n 120 -o cat
    

    Exemple de sortie : ne le collez pas dans la console. Exemple d’erreur résolue par cette procédure :

    https://files.screensoft.org/api/video/H265/1790935600695
    java.lang.IllegalStateException: Received 0 bytes ... /storage/video/1790935600695.mp4

    Received 0 bytes signifie que le lecteur n’a reçu aucun contenu de fichier exploitable. Ce message seul n’en explique pas la raison. Dans cet exemple, l’ID du média est 1790935600695; dans votre cas, relevez l’ID et l’URL exacte dans vos journaux.

    Collez l’adresse exacte des journaux dans le champ en surbrillance ci-dessous ; elle sera insérée automatiquement dans la commande. Conservez les guillemets. Le test ignore les données téléchargées et ne modifie ni les médias ni les listes de lecture. N’utilisez pas systématiquement l’adresse d’exemple pour un autre appareil.

    Collez l’adresse exacte commençant par https:// ou http://, pas le message d’erreur entier ni un chemin /storage/video/…

    L’URL manque. La copie de la commande est désactivée pour le moment.

    2. Vérifiez l’adresse dans la commande, puis copiez tout le bloc. L’adresse est insérée automatiquement.

    Commande à modifier et à copier :

    curl -sS -L --connect-timeout 10 --max-time 30 \
      --range 0-1023 --max-filesize 1048576 \
      -D - -o /dev/null \
      -w '\nHTTP: %{http_code}\nTéléchargé : %{size_download} octets\n' \
      'PASTE_MEDIA_URL_HERE'
    
    Ce que vous voyezSignification et suite à donner
    HTTP 404Le serveur ne fournit pas le média à l’adresse demandée. Identifiez sa campagne à l’étape 6 et corrigez-la à l’étape 7.
    HTTP 401 / 403Le serveur a refusé l’accès. Vérifiez les autorisations et la configuration du service avec l’assistance.
    HTTP 5xxErreur du serveur. Examinez le service de fichiers ; supprimer la liste de lecture ne réparera pas le serveur.
    Erreur DNS, de connexion, de délai ou TLSSuivez l’erreur précise : vérifiez le réseau, la résolution de noms, la disponibilité du serveur, l’heure ou le certificat. Ne désactivez pas la vérification du certificat.
    HTTP 200 / 206 et données non videsLe test a reçu des données. Cela ne confirme pas que la vidéo entière est complète ou lisible ; recherchez d’autres erreurs dans les journaux.
    Limite de taille de curlLe serveur a peut-être ignoré la demande des 1 024 premiers octets. Le test est limité à 1 Mio et 30 secondes ; atteindre une limite ne signifie pas à lui seul que le média est défectueux.
  6. Trouvez la campagne à partir de l’ID du média.

    Saisissez d’abord l’ID du média. La valeur rouge 000 n’est qu’un espace réservé. Le bloc recherche la valeur exacte du champ resourceId, y compris dans les visuels alternatifs, et affiche les campagnes correspondantes. Notez leurs noms et ID. Un bloc inchangé avec la valeur 000 s’arrête sans rien modifier.

    Utilisez le nombre après la dernière barre oblique de l’URL de l’étape 5. Ce n’est ni l’ID de la campagne ni celui de l’appareil. Saisissez-le sans l’extension .mp4.

    L’ID manque. Ne copiez pas encore la commande.

    2. Vérifiez la ligne en rouge, puis copiez toute la commande. Dès qu’un ID valide est saisi, il est inséré automatiquement dans la commande et le bouton Copier est activé.

    Commande à modifier et à copier :

    python3 - <<'PY'
    import json
    RESOURCE_ID = 000  # SAISISSEZ ICI L’ID DU MÉDIA
    if RESOURCE_ID <= 0:
        raise SystemExit('Saisissez d’abord l’ID du média dans RESOURCE_ID.')
    with open('/storage/playlist_new') as f:
        data = json.load(f)
    def contains_resource(value):
        if isinstance(value, dict):
            return value.get('resourceId') == RESOURCE_ID or any(
                contains_resource(v) for v in value.values())
        if isinstance(value, list):
            return any(contains_resource(v) for v in value)
        return False
    found = False
    for c in data.get('campaigns', []):
        if contains_resource(c):
            found = True
            print('Campagne :', c.get('nameCampaign'))
            print('ID de la campagne :', c.get('campaignId'))
            print('Visuel principal :', c.get('primary'))
            print('Visuels alternatifs :', c.get('alternative'))
    if not found:
        print('Média introuvable dans la nouvelle liste. Vérifiez les derniers journaux et l’ID.')
    PY
    

    Si aucun média n’est trouvé, le fichier a peut-être changé entre-temps. Revérifiez les derniers journaux et la nouvelle liste. Si plusieurs campagnes utilisent ce média, en corriger une seule peut ne pas suffire ; vérifiez toutes les correspondances.

  7. Corrigez la campagne dans le portail.

    Ouvrez la campagne identifiée par son nom et son ID. Remplacez le média indisponible par un fichier nouvellement téléversé, ou mettez temporairement la campagne en pause, puis enregistrez. Consultez les guides sur Médias et Campagnes.

    Attendez la réception de la liste mise à jour et le téléchargement de ses médias. Le délai dépend de la connexion et de la taille des fichiers. Répétez les vérifications des étapes 3 et 4 : après la mise en pause ou le remplacement du média, la nouvelle liste ne doit plus référencer le fichier défectueux.

    Si le fichier reste inchangé avec la référence d’origine, la liste mise à jour n’est pas encore arrivée. Vérifiez l’état en ligne et l’enregistrement de la modification dans le portail. Un simple redémarrage ne peut pas rétablir un fichier pour lequel le serveur renvoie toujours HTTP 404. Pour rétablir temporairement les autres publicités, passez à l’étape 8 ; sinon, vérifiez le résultat à l’étape 9.

  8. Réparation locale temporaire avec sauvegarde.

    Procédure de maintenance : interrompt brièvement la diffusion. N’utilisez cette procédure qu’après avoir confirmé le média indisponible et sa campagne. Le script retire une campagne entière de la nouvelle liste, pas seulement sa vidéo. Exécutez-le sur le bon appareil à un moment où une brève interruption est acceptable.

    Le script vérifie tous les ID, arrête uniquement device-runtime.service, sauvegarde les deux fichiers dans /storage/playlist-backup-DATUM-CAS, retire la campagne indiquée de playlist_new et redémarre le service. Il n’écrase pas directement la liste actuelle et ne supprime aucun média. Une sauvegarde est créée avant l’écriture ; si la modification échoue, le script tente de restaurer la nouvelle liste d’origine. En cas d’erreur dans ce bloc, il tente aussi de redémarrer le service, à condition de pouvoir terminer ; une coupure de courant ou un arrêt forcé ne peut pas être géré ainsi.

    Avant l’exécution, renseignez les trois champs ci-dessous :

    • DEVICE_ID: ID numérique de l’appareil de l’étape 4.
    • CAMPAIGN_ID: ID de la campagne de l’étape 6.
    • RESOURCE_ID: ID du média indisponible issu des journaux.

    N’utilisez les ID d’exemple que pour ce cas précis. Les valeurs rouges 000 servent de garde-fou : la copie reste désactivée tant que tous les ID ne sont pas renseignés, et le script inchangé ne modifie rien. Au moins une autre campagne doit rester sur l’appareil.

    1. Saisissez les trois ID avant de copier

    Chaque nombre identifie un élément différent. Vérifiez-les avec les étapes 4 et 6 ; n’utilisez pas systématiquement les valeurs d’exemple.

    Issu de l’étape 4, pas de l’en-tête de la console.

    Issu de l’étape 6 ; ce n’est pas l’ID du média.

    Le même ID de média que celui vérifié à l’étape 6.

    Saisissez les trois ID. La copie de la commande est désactivée pour le moment.

    2. Vérifiez les trois valeurs en rouge, puis copiez tout le bloc. L’exécution interrompt brièvement la diffusion. Le script vérifie aussi que les ID de l’appareil, de la campagne et du média correspondent au contenu de la liste.

    Commande à modifier et à copier :

    sudo python3 - <<'PY'
    import json
    import shutil
    import subprocess
    from datetime import datetime
    from pathlib import Path
    
    DEVICE_ID = 000
    CAMPAIGN_ID = 000
    RESOURCE_ID = 000
    
    if min(DEVICE_ID, CAMPAIGN_ID, RESOURCE_ID) <= 0:
        raise SystemExit('Saisissez d’abord les trois ID. Aucune modification effectuée.')
    
    root = Path('/storage')
    path = root / 'playlist_new'
    service = 'device-runtime.service'
    
    def contains_resource(value):
        if isinstance(value, dict):
            return value.get('resourceId') == RESOURCE_ID or any(
                contains_resource(v) for v in value.values())
        if isinstance(value, list):
            return any(contains_resource(v) for v in value)
        return False
    
    def prepare():
        data = json.loads(path.read_text())
        if data.get('deviceId') != DEVICE_ID:
            raise RuntimeError('L’ID de l’appareil ne correspond pas.')
        matches = [c for c in data.get('campaigns', [])
                   if c.get('campaignId') == CAMPAIGN_ID]
        if len(matches) != 1 or not contains_resource(matches[0]):
            raise RuntimeError('La campagne ou le média ne correspond pas aux ID indiqués.')
        data['campaigns'] = [c for c in data['campaigns']
                             if c.get('campaignId') != CAMPAIGN_ID]
        if not data['campaigns']:
            raise RuntimeError('Aucune campagne ne resterait après l’exclusion.')
        return data
    
    prepare()
    backup = root / ('playlist-backup-' + datetime.now().strftime('%Y%m%d-%H%M%S-%f'))
    backup.mkdir()
    subprocess.run(['systemctl', 'stop', service], check=True)
    saved = False
    try:
        for name in ('playlist', 'playlist_new'):
            shutil.copy2(root / name, backup / name)
        saved = True
        data = prepare()
        path.write_text(json.dumps(data, ensure_ascii=False))
        print('Sauvegarde :', backup)
        print('Campagnes conservées :', len(data['campaigns']))
    except Exception:
        if saved:
            shutil.copy2(backup / 'playlist_new', path)
        raise
    finally:
        subprocess.run(['systemctl', 'start', service], check=True)
    PY
    

    Une sortie réussie indique le chemin de sauvegarde et le nombre de campagnes conservées. Gardez ce chemin pour l’assistance. Si le script signale des ID incohérents, ne retirez pas les contrôles : revenez à l’étape 4 ou 6. Si l’écriture, la restauration ou le démarrage échoue, transmettez la sortie complète à l’assistance ; ne remplacez pas manuellement la liste actuelle par la nouvelle.

    Cette réparation temporaire ne concerne que cet appareil. Elle ne modifie pas les paramètres du serveur. Une mise à jour ultérieure peut renvoyer la campagne défectueuse. Effectuez aussi la correction dans le portail à l’étape 7. Un autre média manquant peut encore bloquer l’activation.
  9. Vérifiez l’activation de la liste et la diffusion réelle.

    Après environ une minute, vérifiez le service et les journaux ; prévoyez davantage de temps pour les gros médias. Ce bloc ne modifie rien.

    Commande à copier :

    systemctl is-active device-runtime.service
    ls -lh --time-style=long-iso /storage/playlist /storage/playlist_new
    sudo journalctl -u device-runtime.service --since "2 minutes ago" --no-pager -o cat | tail -50
    

    Affichez à nouveau les campagnes avec la commande de l’étape 4. La liste actuelle doit contenir la nouvelle sélection attendue, le service être actif et les journaux récents ne plus répéter la même erreur de téléchargement. Des tailles identiques ne suffisent pas à le prouver.

    Enfin, observez l’écran physique ou son aperçu à distance pendant au moins un cycle publicitaire complet. Vérifiez que toutes les campagnes devant être diffusées selon les conditions actuelles apparaissent. Adaptez la durée d’observation aux campagnes planifiées ou espacées dans le temps.

  10. Si le problème persiste.

    • Un autre ID de média apparaît : répétez les étapes 5 et 6 pour le nouveau fichier. Le premier blocage a pu en masquer un autre.
    • La nouvelle liste n’est pas arrivée : vérifiez l’état en ligne, l’appareil ciblé et l’enregistrement de la modification. Une modification locale ne prouve pas que les mises à jour du serveur sont correctement transmises.
    • La liste est active, mais une publicité manque encore : vérifiez ses conditions de planification et les autres erreurs de lecture. Cette procédure ne corrige pas automatiquement tous les problèmes de vidéo ou de planification.
    • Le service ne fonctionne pas : vérifiez son état avec la commande suivante et transmettez le résultat à l’assistance.

    Commande à copier :

    sudo systemctl status device-runtime.service --no-pager

    Transmettez à votre fournisseur l’ID de l’appareil, l’heure locale du problème avec le fuseau horaire, les noms des campagnes attendues, les deux listes, l’erreur pertinente et le résultat du test d’URL. Si vous avez effectué la réparation locale, joignez sa sortie et le chemin de sauvegarde. N’envoyez aucun mot de passe ni identifiant de connexion.

Vous n’avez pas trouvé ce que vous cherchiez ?
Contactez votre fournisseur de logiciel.