[Article] Intégration Pronote : cours, devoirs, notes, etc

j’ai défini aussi ce type de sensor, via une boucle de 10 à 0 et si l’item correspond a l’occurrence de boucle est défini j’utilise son heure de fin sinon je passe au suivant, et si aucun n’est défini alors « pas cours »

Bien plus simple désormais :

                {% if state_attr('sensor.pronote_xxx_l_ane_timetable_today', 'lessons')[0] is defined %}
                 {{state_attr('sensor.pronote_xxx_l_ane_timetable_today', 'day_end_at').strftime('%H:%M')}}
                {% else %}
                 Pas cours
                {% endif %}

Pour mon tableau Réveils et cours je teste une nouvelle option qui averti par un icone si il y a un changement prevu dans l’emploi du temps

image

ÉDIT : j’aime pas, trop d’infos, trop chargé.

1 « J'aime »

Bjr, je travaille sur une prototype pour ajouter QR Code login dans le repo de Delphiki.
Ça va eliminier les soucis avec les ENT/CAS
Pour obtenir le QR Code n’est pas 1-2-3 mais ça marche et je cherche des testers.
Je vais essayer de ajouter le QRCode dans v090 (version séparé de Delphiki pour le moment)
Si intéressé, stp marquer ‹ j’aime ›

4 « J'aime »

J’avais commencé à travailler sur un poc pour pouvoir faire ça (un login par qrcode, en ouvrant la page dans une autre fenêtre et en capturant l’image par les API media des navigateurs, mais finalement, la technique qui permet de se créer un login directement sur pronote en passant outre le CAS marche bien, et je trouve que ça a peu d’intérêt. Si tu ne trouves pas de testeur, je peux toujours trouver quelques minutes pour te servir de cobaye, néanmoins :wink:

Pour moi-même pas trops d’intérêt non plus mais il y a encore tant des gens qui sont bloqué ou leur ENT ne marche pas. En plus… la semaine dernière j’avais des soucis avec mon ENT (site hs) et j’avais pas des soucis avec la connection par QR …

Pour ceux que ça intéressent, je vous transmets quelques sensors pratiques selon les cas.
Ils seront dans leur totalité sur mon github bientôt.

template:
  - sensor:

###### PRONOTE
##MANON
      - name: Dernière mise à jour de Pronote Manon
        unique_id: sensor.derniere_mise_a_jour_de_pronote_manon
        icon: "mdi:update"
        state: "{{ state_attr('sensor.pronote_xxx_manon','updated_at').strftime('%d-%m-%Y à %H:%M') }}"  
        
      - name: Début des cours de Manon - Demain
        unique_id: sensor.debut_des_cours_de_manon_demain
        icon: "mdi:clock-time-five-outline"
        state: >-            
                {% if state_attr('sensor.pronote_xxx_manon_timetable_tomorrow', 'lessons')[0] is defined %}
                 {{state_attr('sensor.pronote_xxx_manon_timetable_tomorrow', 'day_start_at').strftime('%H:%M')}}
                {% else %}
                 Pas cours
                {% endif %}                  

      - name: Fin des cours de Manon - Demain
        unique_id: sensor.fin_des_cours_de_manon_demain
        icon: "mdi:clock-time-five-outline"
        state: >- 
                {% if state_attr('sensor.pronote_xxx_manon_timetable_tomorrow', 'lessons')[0] is defined %}
                 {{state_attr('sensor.pronote_xxx_manon_timetable_tomorrow', 'day_end_at').strftime('%H:%M')}}
                {% else %}
                 Pas cours
                {% endif %} 
            
      - name: Date début des cours de Manon - Demain
        unique_id: sensor.date_debut_des_cours_de_manon_demain
        icon: "mdi:clock-time-five-outline"
        state: >- 
                {% if state_attr('sensor.pronote_xxx_manon_timetable_tomorrow', 'lessons')[0] is defined %}
                 {%- set date = state_attr('sensor.pronote_xxx_manon_timetable_tomorrow', 'day_start_at').strftime('%A %H:%M') 
                    | replace('Monday', 'L.')
                    | replace('Tuesday', 'M.')
                    | replace('Wednesday', 'Me.')
                    | replace('Thursday', 'J.')
                    | replace('Friday', 'V.')
                    | replace('Saturday', 'S.')
                    | replace('Sunday', 'D.') %}
                 {{ date }}
                {% else %}
                 non
                {% endif %}

      - name: Journée de cours de Manon - Demain
        unique_id: sensor.journée_de_cours_de_manon_demain
        icon: "mdi:clock-time-five-outline"
        state: >-            
                {% if state_attr('sensor.pronote_xxx_manon_timetable_tomorrow', 'lessons')[0] is defined %}
                 {{state_attr('sensor.pronote_xxx_manon_timetable_tomorrow', 'day_start_at').strftime('%H:%M')}} - {{state_attr('sensor.pronote_xxx_manon_timetable_tomorrow', 'day_end_at').strftime('%H:%M')}}
                {% else %}
                 Pas cours
                {% endif %} 
                
      - name: Début des cours de Manon - Aujourd'hui
        unique_id: sensor.debut_des_cours_de_manon_aujourd_hui
        icon: "mdi:clock-time-five-outline"
        state: >-            
                {% if state_attr('sensor.pronote_xxx_manon_timetable_today', 'lessons')[0] is defined %}
                  {{state_attr('sensor.pronote_xxx_manon_timetable_today', 'day_start_at').strftime('%H:%M')}}
                {% else %}
                   Pas cours
                {% endif %} 

      - name: Fin des cours de Manon - Aujourd'hui
        unique_id: sensor.fin_des_cours_de_manon_aujourd_hui
        icon: "mdi:clock-time-five-outline"
        state: >- 
                {% if state_attr('sensor.pronote_xxx_manon_timetable_today', 'lessons')[0] is defined %}
                 {{state_attr('sensor.pronote_xxx_manon_timetable_today', 'day_end_at').strftime('%H:%M')}}
                {% else %}
                 Pas cours
                {% endif %} 
               
                                
      - name: Date début des cours de Manon - Aujourd'hui
        unique_id: sensor.date_debut_des_cours_de_manon_aujourd_hui
        icon: "mdi:clock-time-five-outline"
        state: >- 
                {% if state_attr('sensor.pronote_xxx_manon_timetable_today', 'lessons')[0] is defined %}
                 {%- set date = state_attr('sensor.pronote_xxx_manon_timetable_today', 'day_start_at').strftime('%A %H:%M') 
                    | replace('Monday', 'L.')
                    | replace('Tuesday', 'M.')
                    | replace('Wednesday', 'Me.')
                    | replace('Thursday', 'J.')
                    | replace('Friday', 'V.')
                    | replace('Saturday', 'S.')
                    | replace('Sunday', 'D.') %}
                 {{ date }}
                {% else %}
                 non
                {% endif %}
                
      - name: Journée de cours de Manon - Aujourd'hui
        unique_id: sensor.journée_de_cours_de_manon_aujourd_hui
        icon: "mdi:clock-time-five-outline"
        state: >-            
                {% if state_attr('sensor.pronote_xxx_manon_timetable_today', 'lessons')[0] is defined %}
                 {{state_attr('sensor.pronote_xxx_manon_timetable_today', 'day_start_at').strftime('%H:%M')}} - {{state_attr('sensor.pronote_xxx_manon_timetable_today', 'day_end_at').strftime('%H:%M')}}
                {% else %}
                 Pas cours
                {% endif %}  
sensor:
  - platform: template
    sensors:

###### PRONOTE
      next_day_manon:
            value_template: "{{state_attr('sensor.pronote_xxx_manon_timetable_next_day','lessons')[0].start_at.strftime('%Y-%m-%d')}}"
            unique_id: sensor.next_day_manon
            friendly_name: "Prochain Jour de cours Manon"
            
      devoirs_manon:
            unique_id: sensor.devoirs_manon_next_day
            friendly_name: "Devoirs Manon" 
            value_template: "{% set devoirs = namespace(total = 0,fait=0,restant=0) %}
                              {% for state in range(states('sensor.pronote_xxx_manon_homework') | int)  %}
                                {% set homework = state_attr('sensor.pronote_xxx_manon_homework','homework')[state] %}
                                {% if homework.date | string == states('sensor.next_day_manon') %}
                                {% if homework.done  == true  %}
                                  {% set devoirs.fait = devoirs.fait + 1 %}
                                  {%- endif  %}
                                {% set devoirs.total = devoirs.total + 1 %}
                                {%- endif  %}
                              {%- endfor %}
                              {% set devoirs.restant = devoirs.total -  devoirs.fait  %}
                              {{ devoirs.restant  | int != 0 }}"
            attribute_templates:
              devoirs_totaux:  "{% set devoirs = namespace(total = 0) %}
                              {% for state in range(states('sensor.pronote_xxx_manon_homework') | int)  %}
                                {% set homework = state_attr('sensor.pronote_xxx_manon_homework','homework')[state] %}
                                {% if homework.date | string == states('sensor.next_day_manon') %}
                                {% set devoirs.total = devoirs.total + 1 %}
                                {%- endif  %}
                              {%- endfor %}
                              {{devoirs.total}}"
              devoirs_faits:  "{% set devoirs = namespace(fait = 0) %}
                              {% for state in range(states('sensor.pronote_xxx_manon_homework') | int)  %}
                                {% set homework = state_attr('sensor.pronote_xxx_manon_homework','homework')[state] %}
                                {% if homework.date | string == states('sensor.next_day_manon') %}
                                  {% if homework.done  == true  %}
                                    {% set devoirs.fait = devoirs.fait + 1 %}
                                  {%- endif  %}
                                {%- endif  %}
                              {%- endfor %}
                              {{ devoirs.fait}}"
              devoirs_restants:  "{{state_attr('sensor.devoirs_manon','devoirs_totaux') |int - state_attr('sensor.devoirs_manon','devoirs_faits') |int}}"
              pour_le: "{{state_attr('sensor.pronote_xxx_manon_timetable_next_day','lessons')[0].start_at.strftime('%Y-%m-%d') }}" 
              
      devoirs_manon_next_day:
        friendly_name: Devoirs manon pour le prochain jour         
        value_template: >-
            {% set items = states.sensor.devoirs_manon %} 
            {% set devoirs_restants = items.attributes.devoirs_restants %}
            {% set date = as_timestamp(states.sensor.devoirs_manon.attributes.pour_le)  | timestamp_custom("%A %d/%m",true) 
                    | replace('Monday', 'lundi')
                    | replace('Tuesday', 'mardi')
                    | replace('Wednesday', 'mercredi')
                    | replace('Thursday', 'jeudi')
                    | replace('Friday', 'vendredi')
                    | replace('Saturday', 'samedi')
                    | replace('Sunday', 'dimanche') %}    
            {% if devoirs_restants == 0 %}
              Tout est fait pour le {{ date }}
            {% elif devoirs_restants == 1 %}
              {{ devoirs_restants }} devoir non fait pour le {{ date }}
            {% elif devoirs_restants > 1 %}
              {{ devoirs_restants }} devoirs non faits pour le {{ date }}
            {% else %}
              {{ devoirs_restants }} devoirs non faits pour le {{ date }}
            {% endif %}
1 « J'aime »

salut à tous,
au niveau des couleurs pour les evals j’ai parfois de « ? » quel pourrait etre le probleme ?
Capture d'écran 2023-10-06 170217

type: markdown
content: |-
  <div>Evaluations</div> {% set items =
  state_attr('sensor.pronote_vivier_tim_o_evaluations','evaluations')%} <table
  width='100%'>
    <tbody>
    {% for i in range(0, items | count, 1) %}
    <tr><td width='10%'>{{ items[i].date.strftime("%d-%m") }}</td><td width='60%'>{{ items[i].subject }}</td><td width='30%'>
    {% set acquisitions = items[i].acquisitions %}
    {% for j in range(0,acquisitions|count,1) %}{% if acquisitions[j].level == 'Très bonne maîtrise' %}💚{% elif acquisitions[j].level == 'Maîtrise satisfaisante' %}🟢{% elif acquisitions[j].level == "Début de maîtrise" %}🟡{% elif acquisitions[j].level == 'Maîtrise fragile'  %}🟡{% elif acquisitions[j].level == 'Maîtrise insuffisante'  %}🟠{% else %}?{% endif %}{% endfor %}</td></tr>
    {% endfor %}
  </tbody> </table>
card_mod:
  style:
    .: |
      ha-card ha-markdown {
        padding:0px
      }
      ha-card ha-markdown.no-header {
        padding:0px
      }
    ha-markdown$: |
      h1 {
          font-weight: normal;
          font-size: 24px;
      }
      div {
          background-color:rgb(100, 100, 100);
          padding: 12px 12px;
          color:white;
          font-weight:normal;
          font-size:1.2em;
          border-top-left-radius: 5px; 
          border-top-right-radius: 5px; 
      }
      table{
        border-collapse: collapse;
        font-weight:normal;
        font-size:1.em;         
        font-family: Roboto;
        width: auto;
        outline: 0px solid #393c3d;
        margin-top: 10px;
      } caption {
          text-align: center;
          font-weight: bold;
          font-size: 1.2em;
      } td {
          padding: 0px 5px 0px 5px;
          text-align: left;
          border-bottom: 0px solid #1c2020;
      }
      tr {
          border-bottom: 0px solid #1c2020;
          line-height: 4px;
      }
      tr:nth-of-type(even) {
          background-color: rgb(54, 54, 54, 0.3);
      }
      tr:last-of-type {
          border-bottom: transparent;
      }
      mark {
          background: #009767;
          color: #222627;
          border-radius: 10px;
          padding: 5px;
      }
      span {
          background: #EC4B34;
          color: #222627;
          border-radius: 10px;
          padding: 5px;
      }
      span {
          padding: 5px;
      }
      tr:nth-child(n+2) > td:nth-child(2) {
        text-align: left;
      }

Ajoute {{acquisitions[j].abbreviation}} a coté du ? le temps de voir a quoi ca correspond

Dans les niveaux, j’ai un « Presque maîtrisé » également dans la liste. C’est peut être ça !

effectivement ça doit etre ça. il y a 6 niveaux de couleurs normalement.

ligne améliorée et complétée avec « Presque maitrisé » et « Absent »

{% for j in range(0,acquisitions|count,1) %}
{% if acquisitions[j].level == 'Très bonne maîtrise' %}💚
{% elif acquisitions[j].level == 'Maîtrise satisfaisante' %}🟢
{% elif acquisitions[j].level == "Presque maîtrisé" %}🟡
{% elif acquisitions[j].level == "Début de maîtrise" %}🟡
{% elif acquisitions[j].level == 'Maîtrise fragile'  %}🟠
{% elif acquisitions[j].level == 'Maîtrise insuffisante'  %}🔴
{% elif acquisitions[j].level == 'Absent'  %}❌
{% else %}{{acquisitions[j].abbreviation}}
{% endif %}
{% endfor %}</td></tr>

Libre à chacun dans ce code de mettre les emoji les plus adaptés.

Et si on veut juste les réelles abréviations style A+, A etc… Mettre ceci :

    {% set acquisitions = items[i].acquisitions %}
    {% for j in range(0,acquisitions|count,1) %}{{acquisitions[j].abbreviation}}{% endfor %}</td></tr>

Et dans d’autres cartes aussi, si comme moi vous avez des intitulés de matières mal foutus, ou qui prennent trop de place, changez les comme ceci :

{% if items[i].subject == "ANGLAIS LV1 > ANGLAIS LV1" %}ANGLAIS
{% elif items[i].subject == "SC. ECONO.& SOCIALES" %}SES
{% elif items[i].subject == "NUMERIQUE SC.INFORM." %}NSI
{% else %}{{ items[i].subject }}
{% endif %}
1 « J'aime »

Version de test pour QR Code
Pour ne pas poluer le repo de Delphiki, j’ai une version dans le mien. Le mien peut-être viré, modifié, abandonné chaque moment donc ne pas faire un lien.
Après des tests positives et/ou après des fixes, je vais faire un PR pour l’intégrer avec Delphiki

La plus facile est de télécharger le zip et copier le contenu de custom_components/pronote dans votre dossier du même nom (local) de HA, ensuite redémarrer HA

EDIT: maj
Release 0.9.0_dev2 · vingerha/hass-pronote (github.com)

Petite expliquation, obtenir le QR Code json est un peu bizarre mais avec google lens ça marche
vingerha/hass-pronote: Pronote integration for Home Assistant (github.com)

Avec des soucis:
Issues · vingerha/hass-pronote (github.com)

1 « J'aime »

Je ne sais pas si ça peut t’intéresser, mais j’avais justement fait un « proof of concept » qui permettait à l’utilisateur de récupérer le contenu du QR code en ouvrant pronote depuis une autre fenêtre de navigateur et en faisant un screenshot de celle-ci via les API js du navigateur. Comme ça, pas besoin de caméra ni de Google Lens. Je peux essayer d’intégrer le code au flow de configuration, si tu veux (c’était mon objectif au départ, mais comme j’avais finalement pu faire autrement, c’en est resté là). Tu me dis.

1 « J'aime »

Si pas trops difficile, merci oui… mais car scanner le code est juste nécessaire une fois (normalement) n’investise pas trops de temps :slight_smile:

bon ben evidement ça ne fonctionne pas lol.
j’ai essayé de mettre la ligne 8 comme la 11 mais pareil, et inversement.

type: markdown
content: |-
  <div>Evaluations</div> {% set items =
  state_attr('sensor.pronote_vivier_tim_o_evaluations','evaluations')%} <table
  width='100%'>
    <tbody>
    
    {% for i in range(0, items | count, 1) %}
    <tr><td width='10%'>{{ items[i].date.strftime("%d-%m") }}</td><td width='60%'>{{ items[i].subject }}</td><td width='30%'>
    {% set acquisitions = items[i].acquisitions %}
    {% for j in range(0,acquisitions|count,1) %}
    {% if acquisitions[j].level == 'Très bonne maîtrise' %}💚
    {% elif acquisitions[j].level == 'Maîtrise satisfaisante' %}🟢
    {% elif acquisitions[j].level == "Presque maîtrisé" %}🟡
    {% elif acquisitions[j].level == "Début de maîtrise" %}🟡
    {% elif acquisitions[j].level == 'Maîtrise fragile'  %}🟠
    {% elif acquisitions[j].level == 'Maîtrise insuffisante'  %}🔴
    {% elif acquisitions[j].level == 'Absent'  %}❌
    {% else %}{{acquisitions[j].abbreviation}}
    {% endif %}
    {% endfor %}</td></tr>
  </tbody> </table>
card_mod:
  style:
    .: |
      ha-card ha-markdown {
        padding:0px

À avoir regardé très rapidement de mon téléphone j’ai l’impression qu’il te manque une balise endfor, donc mets en deux à la fin comme ceci :

{% endfor %}{% endfor %}</td></tr>

excellent c’etait bien ça. merci.
reste juste un probleme sur cette carte.
maintenant les couleurs se retrouvent affiché verticalement et plus horizontalement comme avant. j’ai essayé de jouer sur quelques parametres mais rien à faire.

Essaye de mettre la deuxième balise endfor mais en tout dernier sur ce que je t’ai fait (après /tr)

toujours pareil

content: |-
  <div>Evaluations</div> {% set items =
  state_attr('sensor.pronote_vivier_tim_o_evaluations','evaluations')%} <table
  width='100%'>
    <tbody>
    {% for i in range(0, items | count, 1) %}
    <tr><td width='10%'>{{ items[i].date.strftime("%d-%m") }}</td><td width='60%'>{{ items[i].subject }}</td><td width='30%'>
    {% set acquisitions = items[i].acquisitions %}
    {% for j in range(0,acquisitions|count,1) %}
    {% if acquisitions[j].level == 'Très bonne maîtrise' %}💚
    {% elif acquisitions[j].level == 'Maîtrise satisfaisante' %}🟢
    {% elif acquisitions[j].level == "Presque maîtrisé" %}🟡
    {% elif acquisitions[j].level == "Début de maîtrise" %}🟡
    {% elif acquisitions[j].level == 'Maîtrise fragile'  %}🟠
    {% elif acquisitions[j].level == 'Maîtrise insuffisante'  %}🔴
    {% elif acquisitions[j].level == 'Absent'  %}❌
    {% else %}{{acquisitions[j].abbreviation}}
    {% endif %}
    {% endfor %}</td></tr>
    {% endfor %}

Le template est appliqué tel que défini. Il faut concatener les if elif sur la même ligne afin d’avoir l’affichage souhaité.
Voilà ce que j’ai chez moi afin d’avoir tout sur une ligne.

{% for j in range(0,acquisitions|count,1) %}{% if acquisitions[j].level == 'Très bonne maîtrise' %}💚{% elif acquisitions[j].level == 'Maîtrise satisfaisante' %}🟢{% elif acquisitions[j].level == "Début de maîtrise" %}🟡{% elif acquisitions[j].level == 'Maîtrise fragile'  %}🟠{% elif acquisitions[j].level == 'Maîtrise insuffisante'  %}🔴{% elif acquisitions[j].level == 'Presque maîtrisé'  %}🔵{% else %}👽{% endif %}{% endfor %}</td></tr>