Sartog - De retour (un peu) et un nouveau design en cours

Bien le bonjour tout le monde,

Voilà bien longtemps que je n’ai pas donné signe de vie, faute de temps et faute à Jeedom qui tournait bien :rofl:

Mais le passage à la V4 m’a obligé, comme beaucoup, à dépoussiérer mes connaissances en html/css/js pour reprendre mon design V3 tout cassé.
Du coup, c’est l’excuse pour reprendre le projet de domotisation de la maison mis en stand-by il y a plus de 2 ans … déjà !

Alors avec ce post j’ajoute ma pierre à l’édifice du partage de mes visuels et de mes idées (plus ou moins bonne) de widget, virtuel et autre.
Je verrais, si j’avance sur les projets, pour les partager (suivis niveau cuve eau de pluie, arrosage, etc.) avec vous.

En attendant, voici les premières images de mon design en mode conception (il manque pas mal d’info, il faut agencer tout cela, etc.).

Nous utilisons depuis sa sortie majoritairement Alexa, reléguant la tablette affichant le design à principalement un check au moment du départ / arrivé plutôt qu’un tableau de bord de commande de la maison.
Donc nous y avons essentiellement des informations.
Pour les actions que j’implémente malgré tout (si un jour Alexa bug), soit elles sont sous forme de bouton pour action direct (fermer tous les volets par exemple), soit par des zone de survol affichant l’équipement au clic et, en dernier recours, à l’ouverture d’une nouvelle page.

Voici la page d’accueil (en cours de construction pour rappel. Les cadres en bas à droite sont en stand-by d’être utilisés ou supprimés) :
Jeedom - Acceuil

A gauche :

  • Un cadre d’action / info global contenant :
    • L’état de marche du ballon d’eau chaude (vert si en marche / gris si à l’arrêt). Un clique dessus le fait changer d’état. J’aimerais le domotiser plus en récupérant le niveau d’eau chaude à l’intérieur, mais risquer une mauvaise manip cramant la carte électronique / sonde de niveau, rendant ainsi HS le ballon me refroidit (sans mauvais jeu de mots :man_facepalming:)

    • L’état de la cartouche Brita (sinon on ne pense jamais à changer cette cartouche). Un clique dessus affiche un widget au survol permettant d’indiquer le changement de cartouche (clique sur le bouton New)
      Jeedom - Brita

    • La couleur de la poubelle à sortir (gris ce n’est pas le jour / vert ou jaune suivant les semaines)

    • L’ouverture ou fermeture de tous les volets.

  • Un cadre des modes et état de l’alarme :
    • Le clique sur une tête permet d’afficher un widget au survol pour piloter le mode (au cas où la détection automatique à loupée)
      Jeedom - Mode

    • L’état de l’alarme de la maison (aucune action dessus pour l’instant).

    • L’état des détecteurs d’incendie et de fuite (si une détection, l’icone passe au rouge et « pulse »)

    • Et en bas à droite, la synthèse des capteurs de mouvement (gris pas de mouvement / rouge au moins 1 capteur à détecté un mouvement). Le clique dessus affiche un widget au survol de tous les capteurs et durée depuis le dernier mouvement (permet de vérifier qu’un capteur n’a pas été déplacé ou est tombé en rade de pile alors que le système dit qu’il y en a encore)
      Jeedom - Mouvement

En central :

  • un widget météo perso affichant les informations d’un virtuel centralisant les informations en provenance du plugin officiel Weather et de Netatmo.
  • En dessous, la centralisation des températures des pièces (vert T°en hausse, gris T° stable et jaune orange T° en baisse).

A droite :

  • Une horloge (car c’est toujours bien d’afficher l’heure)
  • La synthèse des lumières : le pilotage par zone cliquable ouvrant l’équipement (ou les équipements) concerné ou plutôt l’ouverture d’une page global est à la réflexion.
  • La synthèse des volets : cliquer sur la synthèse ouvrira une page dédié (13 volets roulants, s’était trop lourd à mettre en zone cliquable).
  • La synthèse des fenêtres, c’est juste informatif (avec durée d’ouverture de la journée).

La page de pilotage des volets n’a rien d’exceptionnelle (aussi en construction) :
Jeedom - Volet

J’ai une 3ème page spécifique (pour l’instant) qui s’affiche sur la tablette lorsqu’une personne sonne au portail (via scénario et JPI de @dJuL ) et qui permet d’ouvrir le portail (mais je crois que nous ne l’avons jamais utilisé, nous utilisons toujours Alexa ou la télécommande du portail :rofl:).

La mise en page se fait principalement par du CSS via Réglage/Personnalisation avancée (un peu plus de 660 lignes actuellement, des fichiers css/js/font spécifique pour la météo et l’horloge (stockés dans data/plan avec .htaccess adapté) et quelques widgets de mon cru.

L’utilisation de Réglage/Personnalisation avancée pour le css permet énormément de chose, dont la mise en page des équipements complets (notamment quand ils sont affichés dans la zone de survol) sans toucher à leur mise en page par défaut du dashboard et en poussant plus loin que les possibilités de la disposition par tableau accessible via Configuration avancée/Disposition de l’équipement.

Mon installation se base sur :

  • Une Smart
  • du Zwave (volets, certaines lumières, radiateur et sèche-serviette, détecteur de mouvement, de fumée et d’inondation)
  • du Zigbee (ouverture ouvrant, je prévois d’intégrer les ampoules Ikea actuellement liées à la passerelle Ikea)
  • un ipx800 v4
  • Un doorbird
  • des caméra Hikvision (mais je songe à les changer, elles ont fait leur temps)

Voilà pour l’instant.
Je suis conscient qu’il y a encore beaucoup à faire, et je suis à l’écoute des idées / propositions / critiques constructives / interrogations.
Merci à vous d’avoir pris le temps et le courage de tout lire.

Et j’espère pouvoir vous présenter rapidement les évolutions.

12 J'aimes

Mais que c’est beauuu ce thème en blanc, hyper inspirant :wink:

Bravo @sartog !!!

J ai hâte de voir la suite.
Bon courage.

Bravo
Ça c’est un design vraiment top
Il va falloir que je me remette aussi la test dans le cas HTML.

Merci pour vos messages.

J’ai en effet essayé de faire un visuel pas trop « agressif » et je trouvais que la tendance « Neumorphisme » actuelle s’y prêtait bien.

Je suis en discussion avec un vendeur d’une grande enseigne web Chinoise (je ne sais plus si nous avons le droit de nommer les sites) pour mon capteur de pression (capteur différentiel afin de prendre en compte la variation de pression atmosphérique) destiné à mesurer le niveau d’eau dans ma cuve d’eau de pluie, raccordé au Smart Implant de Fibaro.

En parallèle, je dois modifier mon tableau électrique en achetant un contacteur de puissance pour piloter mon éclairage extérieur car j’ai trop de LED (pour un total de 180W sur un circuit).
Les relais de l’IPX ne sont pas fait pour supporter l’Intensité d’appel important des LED et risquent de rester coller / crâmer (expliquant pourquoi il me fallait parfois appuyer plusieurs fois sur mon interrupteur pour que les lumières restent allumées).
Je pensais passer par des modules Z-wave dans des modules rail-DIN, mais Fibaro indique aucune valeur pour les charges capacitives (LED) et donc se dédouane en cas de problème (et ce que j’ai lu sur le web n’est pas encourageant).
Du coup, obligé de passer par la méthode traditionnelle, un bon contacteur de puissance modulaire dont la bobine sera piloter par l’IPX ou un Fibaro.
(Quand j’ai changé mes ampoules pour des LED je n’avais pas du tout cette subtilité en tête).

Je profiterais surement d’avoir la tête dans mon tableau pour y ajouter lepilotage des prises extérieures via des Fibaro sur rail-Din (afin de piloter l’éclairage décoratif d’Haloween / Noël).

J’essais de vous faire un retour dès que c’est fonctionnel.

1 J'aime

Le sujet m’intéresse, as-tu déjà ouvert un fil ou pas encore ? Merci :wink:

Pas encore.

Je vais essayer de documenter le matos, câblage, etc. quand j’aurais tout ça sous la main et en place.

Dans les grandes ligne, je ne voulais pas m’embêter avec la solution capteur ultrason / Raspberry (ou Arduino) car :

  • Mettre un Pi juste pour ça je trouve que c’est un peu extrême (ou alors un Pi nano)
  • Mettre un Arduino (ou autre module du genre) nécessite de mettre en place de l’électronique et un serveur qui push les donner à Jeedom (ou un serveur qui accepte les interrogations Jeedom)
  • Là où le matos sera installé (en bordure de terrasse, en extérieur), je n’ai pas une très bonne couverture Wifi
  • Il faut prendre un capteur Ultrason résistant au milieu humide sinon ça ne dur pas longtemps
  • Faut bidouiller

N’ayant pas le temps de me pencher sur la programmation d’un Arduino, pas le temps pour de l’électronique, et n’ayant pas une couverture stable Wifi là où ce sera installé, j’ai préféré partir sur une solution un peu moins bricolée avec un Fibaro Smart Implant (pas de problème de réseau Z-Wave là où il sera installé, à contrario du wifi) et un capteur de pression immergée (pas de problème avec l’humidité du coup vu qu’il est prévu pour :rofl:).

Le Smart Implant peut être connecté à un capteur fonctionnant en 0-10V, du coup théoriquement il n’y a pas grand chose à faire (0v = 0m / 10V = le niveau max du capteur de pression).

Le capteur de pression, lui doit être différentiel (c’est à dire qu’il prend la pression de la colonne hydrostatique et la pression atmosphérique afin de retourner la hauteur d’eau).
Si il n’est pas différentiel, ta mesure du niveau d’eau va bouger toute seule en fonction de la pression atmosphérique.
A chacun de déterminer si c’est important ou pas.
Chez moi, d’un extrême à l’autre ça me ferait 56cm de différence (si j’ai bien compté) et le risque que ma pompe tourne à vide (bon même si elle a normalement une sécurité pour cela, mais elle m’a déjà fait le coup de tourner à vide alors maintenant je suis méfiant).

J’essaierais de faire un billet plus détaillé dès que ce sera opérationnel (avec le COVID, je ne connais pas les délais de livraison depuis la Chine alors ça risque d’être long).

1 J'aime

Sympa le design

Superbe design @sartog :+1:t2::+1:t2: sobre et classe !
Je travaille actuellement sur un design « flat » mais tu viens de me perturber avec tes screenshot :rofl:
Tu accepterais de partager ton travail ?
Merci d’avance

Xav

@Xav-74, je m’étais justement fait la réflexion ce matin que je n’avais pas partagé mon code, un oublis de ma part que je vais corriger de suite :wink:

J’ai fais le screen ci-après avec les différents visuels css que j’ai à disposition pour mon design afin de permettre de rapprocher le code css au visuel (pour ceux qui veulent qu’une partie du code).
Pour information, j’ai mis mon code css dans Réglage/Personnalisation avancée (sauf pour le widget météo et pour l’horloge).

En espérant que ce soit clair pour tous (sinon n’hésitez pas à demander).

Jeedom - Cadre

  • Body :
[data-page="plan"] .div_displayObject {
  background: #E7EEF7 !important;
  font-family: system-ui !important;
}

Le [data-page=« plan »] permet d’appliquer le code CSS uniquement au design.

  • Les couleurs d’icone ou d’écriture :
.mia-inactif {
  color: rgba(167, 172, 177, 1);
}

.mia-jaune {
  color: rgba(214, 158, 46, 1);
}

.mia-vert {
  color: rgba(72, 187, 120, 1);
}

.mia-rouge{
  color: rgba(255, 82, 82, 1); 
}
  • Cadre n°1 :
[data-page="plan"] .mia-cadre{
  width: 100%;
  height: 100%;
  background: transparent;
  border-radius: 32px; 
  box-shadow: 5px 5px 10px 5px rgba(136, 165, 191, 0.5),
    -5px -5px 10px 5px rgba(255,255,255, 0.8);
}

Un exemple de mise en place (identique pour les autres cadres) :
Jeedom - exemple cadre

  • Cadre n°2 :
[data-page="plan"] .mia-cadre-inset{
  width: 100%;
  height: 100%;
  background: transparent; 
  border-radius: 32px;
  box-shadow: inset 5px 5px 10px 5px rgba(136, 165, 191, 0.5),
    inset -5px -5px 10px 5px rgba(255,255,255, 0.8);
}
  • Cadre n°3 :
[data-page="plan"] .mia-cercle{
  width: 100%;
  height: 100%;
  background: transparent; 
  border-radius: 50%;
  box-shadow: 5px 5px 10px 5px rgba(136, 165, 191, 0.5),
    -5px -5px 10px 5px rgba(255,255,255, 0.8);
}
  • Cadre n°4 :
[data-page="plan"] .mia-cercle-inset{
  width: 100%;
  height: 100%;
  background: transparent; 
  border-radius: 50%;
  box-shadow: inset 5px 5px 10px 5px rgba(136, 165, 191, 0.5),
    inset -5px -5px 10px 5px rgba(255,255,255, 0.8);
}
  • Cadre n°5 :
[data-page="plan"] .mia-cercle-double{
  width: 100%;
  height: 100%;
  display: flex;
  justify-content: center;
  align-items: center;
  background: transparent;
  background-size: cover;
  border-radius: 50%;
  box-shadow: inset 5px 5px 10px 5px rgba(136, 165, 191, 0.5),
    inset -5px -5px 10px 5px rgba(255,255,255, 0.8);
}

[data-page="plan"] .mia-cercle-double::after{
  content: "";
  height: 50px;
  width: 50px;
  position: absolute;
  border-radius: 50%;
  box-shadow: 5px 5px 10px 5px rgba(136, 165, 191, 0.5),
     -5px -5px 10px 5px rgba(255,255,255, 0.8);
  z-index: 2;
}
  • Label et sous label d’un cadre :
[data-page="plan"] .mia-cadre-label {
  padding-top: 5px;
  text-align: center;
  font-size: 17px;
  font-weight: bolder;
  line-height: 17px;
}
[data-page="plan"] .mia-cadre-sous-label {
  font-size: 16px;
  font-weight: lighter;
  line-height: 16px;
}

Pour sa mise en place, voici un exemple :
Jeedom - Cadre label

  • Pour le texte (Label normal et Label en gras) , j’utilise principalement :
[data-page="plan"] .mia-label {
  font-size: 13px;
  font-weight: lighter;
  line-height: 13px;
}

[data-page="plan"] .mia-label-bold {
  font-size: 17px;
  font-weight: bolder;
  line-height: 17px;
}
  • Pour les boutons On et Off :
.mia-bouton-off {
  height: 60px;
  width: 60px;
  position: relative;
  margin: 10px;
  background: transparent;
  border-radius: 25px;
  border: 0;
  box-shadow: 5px 5px 15px rgba(136, 165, 191, 0.5), 5px 5px 15px rgba(255,255,255, 0.8), -2px -2px 2px rgba(255,255,255, 0.8);
}
.mia-bouton-on {
  height: 60px;
  width: 60px;
  position: relative;
  margin: 10px;
  background: transparent;
  border-radius: 25px;
  border: 0;
  box-shadow: inset 5px 5px 15px rgba(136, 165, 191, 0.5), inset 5px 5px 15px rgba(255,255,255, 0.8), inset -2px -2px 2px rgba(255,255,255, 0.8);
}
.mia-bouton-on:hover, 
.mia-bouton-off:hover,
.mia-bouton-on-tiny:hover,
.mia-bouton-off-tiny:hover {
  background: rgba(255, 255, 255, 0.24);
}
  • Pour les boutons On et Off version tinny (utilisés pour les boutons des volets roulants par exemple) :
.mia-bouton-off-tiny{
  height: 40px;
  width: 40px;
  position: relative;
  margin: 5px;
  background: transparent;
  border-radius: 25px;
  border: 0;
  box-shadow: 2px 2px 10px rgba(136, 165, 191, 0.5), 2px 2px 10px rgba(255,255,255, 0.8), -2px -2px 2px rgba(255,255,255, 0.8);
}
.mia-bouton-on-tiny{
  height: 40px;
  width: 40px;
  position: relative;
  margin: 5px;
  background: transparent;
  border-radius: 25px;
  border: 0;
  box-shadow: inset 2px 2px 10px rgba(136, 165, 191, 0.5), inset 2px 2px 10px rgba(255,255,255, 0.8), inset -2px -2px 2px rgba(255,255,255, 0.8);
}

Pour utiliser les boutons, dans le widget il faut renseigner cette base :
Jeedom - Btn simple

Ensuite, il suffit de mettre ce que vous souhaitez entre les balise button, voici un exemple pour le bouton permettant d’allumer / arrêter mon cumulus :
Jeedom - Btn cumulus

7 J'aimes

Merci infiniment @sartog ! Je sais ce que je vais faire ce week-end :stuck_out_tongue_winking_eye:

Xav

Concernant l’horloge :
Jeedom - horloge

Cette dernière est affichée directement via un bloc html sur la page du design :
Jeedom - horloge 2
Avec ce code :

<link rel="stylesheet" href="/data/plan/css/clock.css">

<div class="clock">
  <div class="hour">
    <div class="hr" id="hr"></div>
  </div>
  <div class="min">
    <div class="mn" id="mn"></div>
  </div>
</div>

<script src="/data/plan/js/clock.js"></script>

Ce code HTML fait donc appel à 2 fichiers différents (1 fichier css et 1 fichier js) stockés dans le dossier data/plan.
Jeedom - data

Le fichier css (clock.css) contient ceci :

.clock{
    width: 100px;
    height: 100px;
    display: flex;
    justify-content: center;
    align-items: center;
    background: url(../img/clock.png);
    background-size: cover;
    border-radius: 50%;
    box-shadow: inset 5px 5px 10px 5px rgba(136, 165, 191, 0.5),
    inset -5px -5px 10px 5px rgba(255,255,255, 0.8);
}

.clock::before{
    content: "";
    position: absolute;
    height: 20px;
    width: 20px;
    background-color: #E7EEF7;
    border-radius: 50%;
    box-shadow: 5px 5px 10px 5px rgba(136, 165, 191, 0.5),
      -5px -5px 10px 5px rgba(255,255,255, 0.8);
}

.clock .hour,
.clock .min{
    position: absolute;
}

.clock .hour, .hr {
    width: 60px;
    height: 60px;
}

.clock .min, .mn{
    width: 80px;
    height: 80px;
}

.hr, .mn {
    display: flex;
    justify-content: center;
    position: absolute;
    border-radius: 50%;
}

.hr::before{
    content: "";
    position: absolute;
    width: 3px;
    height: 30px;
    background-color: #555555;
    z-index: 10;
    border-radius: 6px 6px 0 0;
}

.mn::before{
    content: "";
    position: absolute;
    width: 2px;
    height: 40px;
    background-color: #959595;
    z-index: 11;
    border-radius: 6px 6px 0 0;
}

Et le fichier javascript (clock.js) contient ceci :

var deg = 6;
var hr = document.querySelector("#hr");
var mn = document.querySelector("#mn");

setInterval(() =>{
    let day = new Date();
    let hh = day.getHours() * 30;
    let mm = day.getMinutes() * deg;

    hr.style.transform = `rotateZ(${(hh) + (mm / 12)}deg)`;
    mn.style.transform = `rotateZ(${mm}deg)`;
})

J’attire votre attention sur 2 points concernant le stockage de vos fichiers sources dans data/plan :

  • Mettre ses fichiers sources dans data/plan évite à ces derniers d’être effacés par le système à chaque mise à jour (avant je les stockais dans desktop/theme).
  • Le .htaccess du dossier data/plan bloque l’accès au fichier autre qu’image. Il faut donc modifier le .htaccess ainsi :
Order allow,deny
<Files ~ "\.(css|js|eot|svg|ttf|woff|woff2|jpeg|png|jpg)$">
allow from all
</Files>
Deny from all

La modification de ce fichier se fait en ssh.

Edit : Une alternative plus facile à mettre en œuvre consiste au stockage de vos fichiers sources dans un dossier que vous créez dans desktop (par exemple un dossier montheme).
Ainsi vous éviter l’effacement de vos fichiers sources aux mise à jour ET vous n’avez pas besoin de modifier le .htaccess.

4 J'aimes

Concernant la météo :
Jeedom - meteo

Ce dernier est un widget appliqué sur un virtuel et se décompose de 3 parties :

  • La partie supérieur, indiquant :
    • la météo actuelle (source : plugin météo officiel)
    • la température réelle mesurée (source : plugin Netatmo - module extérieur)
  • La partie centrale, indiquant :
    • L’heure du lever et coucher de soleil (source : plugin météo officiel)
    • Température mini et maxi du jour (source : plugin météo officiel)
    • Direction du vent, vitesse et rafale (source : plugin Netatmo - anénomètre)
    • Pluviométrie du jour et pluviométrie prévisionnelle (source : plugin Netatmo - pluviomètre et plugin météo officiel)
  • La partie basse, indiquant :
    • La météo pour les 3 jours à venir
    • Température mini et maxi pour les 3 jours à venir.

Voici les éléments qui constituent cela :

  • Virtuel :
    Concernant le virtuel, rien de compliqué.
    Une commande de type info et sous-type « autre » suffit.
    Dans valeur, l’ensemble des informations dont j’ai besoin :
    Jeedom - virtuel

  • Le Widget :
    Il faut créer un widget Code de type Info / Autre
    Jeedom - Creation

et y mettre le code suivant :

<div class="cmd-widget" data-type="info" data-subtype="string" data-template="default" data-cmd_id="#id#" data-cmd_uid="#uid#" data-version="#version#" data-eqLogic_id="#eqLogic_id#">

  <link rel="stylesheet" href="/data/plan/icons/weather-underground/wu-icons-style.css">
  <link rel="stylesheet" href="/data/plan/icons/weather-icons/weather-icons.css">
  <link rel="stylesheet" href="/data/plan/icons/weather-icons/weather-icons-wind.css">
  <link rel="stylesheet" href="/data/plan/css/weather.css">

  <div class="mia-meteo-cadre">

    <!-- 1er cadre : météo actuelle -->
    <div class="" id="mia-meteo-cadre-now">
      <span class="" id="mia-meteo-now-icone"></span>
      <span class="" id="mia-meteo-now-temperature"></span>
      <span class="" id="mia-meteo-now-temps"></span>
    </div>

    <!-- 2nd cadre : détail météo actuelle -->
    <div class="mia-meteo-cadre-detail">
      <div class="mia-meteo-detail-grid">
        <span class="mia-meteo-detail-texte" id="mia-meteo-lever-soleil"></span>
        <span class="mia-meteo-detail-texte" id="mia-meteo-coucher-soleil"></span>
        <span class="mia-meteo-detail-texte" id="mia-meteo-now-temperature-mini"><i class="wi wi-thermometer-exterior"></i></span>
        <span class="mia-meteo-detail-texte" id="mia-meteo-now-temperature-maxi"><i class="wi wi-thermometer"></i></span>
        <span class="mia-meteo-detail-texte" id="mia-meteo-now-vent-icone"></span>
        <span class="mia-meteo-detail-texte" id="mia-meteo-now-vent"></span>
        <span class="mia-meteo-detail-texte"><i class="mia-meteo-detail-icone-pluie wi wi-raindrops"></i></span>
        <span class="mia-meteo-detail-texte" id="mia-meteo-now-pluie"></span>
      </div>
    </div>

    <!-- 3ème cadre : météo à venir -->
    <div class="mia-meteo-cadre-prevision-grid">
      <div>
        <span class="mia-meteo-prevision-jour" id="mia-meteo-jour1-nom"></span>
        <span class="" id="mia-meteo-jour1-icone"></span>
        <span class="mia-meteo-prevision-temperature" id="mia-meteo-jour1-temperature"></span>
      </div>
      <div>
        <span class="mia-meteo-prevision-jour" id="mia-meteo-jour2-nom"></span>
        <span class="" id="mia-meteo-jour2-icone"></span>
        <span class="mia-meteo-prevision-temperature" id="mia-meteo-jour2-temperature"></span>
      </div>
      <div>
        <span class="mia-meteo-prevision-jour" id="mia-meteo-jour3-nom"></span>
        <span class="" id="mia-meteo-jour3-icone"></span>
        <span class="mia-meteo-prevision-temperature" id="mia-meteo-jour3-temperature"></span>
      </div>
    </div>

  </div>

  <script src="/data/plan/js/weather.js"></script>
  <script>
    jeedom.cmd.update['#id#'] = function(_options){
      
      mia_meteo(_options.display_value);
      
    }

    jeedom.cmd.update['#id#']({display_value:'#state#'});
  </script>

</div>
  • Les fichiers sources :
    A l’image de l’horloge (voir message avant celui-ci), mes fichier sources sont stockés dans data/plan.
    Pour ce widget, il y a plusieurs fichiers :

  • weather.css : contient le css du widget

  • weather.js : contient le code javascript permettant l’affichage de toutes les informations

  • wu-icons-style.css : pour les icônes des prévision

  • weather-icons.css : pour les icônes de la météo actuelle

  • weather-icons-wind.css : pour les icônes du vent

  • weather.png : c’est l’image représentant les arbres et montagne habillant la partie haute du widget.

Le fichier css (weather.css) contient ceci :

/* cadre principal */

.mia-meteo-cadre {
    width: 300px;
    height: 610px;
    background: transparent;
    border-radius: 32px;
    box-shadow: 5px 5px 10px 5px rgba(136, 165, 191, 0.5), -5px -5px 10px 5px rgba(255, 255, 255, 0.8);
}


/***** cadre 1 *****/

.mia-meteo-cadre-now {
    width: 300px;
    height: 250px;
    display: grid;
    grid-gap: 0px;
    grid-template-columns: 150px 150px;
    grid-template-rows: 130px 40px;
    border-radius: 25px 25px 0 0;
    background: url(../img/weather.png) no-repeat bottom/100%;
}

.mia-meteo-now-soleil {
    background-color: #87CEFA;
}

.mia-meteo-now-nuageux {
    background-color: #B0C4DE;
    filter: saturate(70%);
}

.mia-meteo-now-pluie {
    background-color: #719dc0;
    filter: grayscale(40%);
}

.mia-meteo-now-orage {
    background-color: #4682B4;
    filter: grayscale(50%);
}

.mia-meteo-now-neige {
    background-color: #FFFAFA;
}

.mia-meteo-now-nuit {
    background-color: #191970;
    filter: grayscale(50%);
}

.mia-meteo-now-icone {
    grid-column: 1;
    grid-row: 1;
    margin-left: 10px;
}

.mia-meteo-now-temperature,
.mia-meteo-now-temps {
    padding-right: 20px;
    text-align: right;
    font-family: inherit;
    font-weight: lighter;
}

.mia-meteo-now-temperature {
    grid-column: 2;
    grid-row: 1;
    padding-top: 35px;
    font-family: Tahoma, Geneva, sans-serif;
    font-size: 70px;
}

.mia-meteo-now-temps {
    grid-column: 1/3;
    grid-row: 2;
    margin-right: 5px;
    font-family: Cambria, serif;
    font-size: 30px;
    white-space: nowrap;
}

.mia-meteo-now-color-white {
    color: white;
}

.mia-meteo-now-color-blue {
    color: rgb(44, 103, 180);
}


/***** cadre 2 *****/

.mia-meteo-cadre-detail {
    width: 290px;
    height: 150px;
    margin-top: 20px;
    margin-left: 10px;
    margin-right: 0px;
    background: transparent;
    border-radius: 25px 0 0 25px;
    box-shadow: inset 5px 5px 10px 0px rgba(136, 165, 191, 0.5), inset -5px -5px 10px 0px rgba(255, 255, 255, 0.8);
}

.mia-meteo-detail-grid {
    width: 290px;
    height: 140px;
    padding-top: 15px;
    display: grid;
    grid-template-columns: 50% 50%;
    grid-template-rows: 1fr 1fr 1fr;
    grid-gap: 0px;
    grid-column-gap: 0px;
}

.mia-meteo-detail-grid span:nth-child(1) {
    grid-column: 1;
    grid-row: 1;
    text-align: left;
    text-indent: 30px;
}

.mia-meteo-detail-grid span:nth-child(2) {
    grid-column: 2;
    grid-row: 1;
    text-align: left;
    text-indent: 10px;
}

.mia-meteo-detail-grid span:nth-child(3) {
    grid-column: 1;
    grid-row: 2;
    text-align: left;
    text-indent: 34px;
}

.mia-meteo-detail-grid span:nth-child(4) {
    grid-column: 2;
    grid-row: 2;
    text-align: left;
    text-indent: 14px;
}

.mia-meteo-detail-grid span:nth-child(5) {
    grid-column: 1;
    grid-row: 3;
    text-align: left;
}

.mia-meteo-detail-grid span:nth-child(6) {
    grid-column: 1;
    grid-row: 3;
    text-align: left;
    text-indent: 75px;
}

.mia-meteo-detail-grid span:nth-child(7) {
    grid-column: 2;
    grid-row: 3;
    text-align: left;
}

.mia-meteo-detail-grid span:nth-child(8) {
    grid-column: 2;
    grid-row: 3;
    text-align: left;
    text-indent: 40px;
}

.mia-meteo-detail-texte {
    display: inline-block;
    color: #A7ACB1;
    font-weight: lighter;
    font-family: Cambria, serif;
    font-size: 20px;
    line-height: 1.5;
}

.mia-meteo-detail-icone-vent {
    font-size: 40px;
    position: relative;
    top: -5px;
    left: 45px;
}

.mia-meteo-detail-icone-pluie {
    font-size: 40px;
    position: relative;
    top: -5px;
    left: 25px;
}

/***** Cadre 3 *****/

.mia-meteo-cadre-prevision-grid {
    width: 290px;
    height: 170px;
    margin-top: 20px;
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    grid-column-gap: 0px;
}

.mia-meteo-cadre-prevision-grid div {
    width: 80px;
    height: 150px;
    margin-left: auto;
    margin-right: auto;
    background: transparent;
    border-radius: 25px;
    box-shadow: 5px 5px 10px 0px rgba(136, 165, 191, 0.5), -5px -5px 10px 0px rgba(255, 255, 255, 0.8);
    text-align: center;
    line-height: 2;
}

.mia-meteo-prevision-jour {
    display: block;
    margin-top: 10px !important;
    color: #A7ACB1;
    font-family: Cambria, serif;
    font-weight: lighter;
    font-size: 12px;
}

.mia-meteo-prevision-temperature {
    display: block;
    color: #A7ACB1;
    font-family: Tahoma, Geneva, sans-serif;
    font-weight: lighter;
    font-size: 14px;
}

Le fichier js (weather.js) contient ceci :

function mia_meteo(_valeur){
    // Initialisation des variables.
    var valeur = _valeur.split(',');
    const cond_pluie = ["312", "500", "501", "531", "615", "616"];
    const cond_averse = ["313", "314", "502", "503", "504", "520", "521", "522", "620"];
    const cond_crachin = ["300", "301", "302", "310", "311", "321"];
    const cond_neige = ["600", "601", "602", "621", "622"];
    const cond_neige_fondue = ["611", "612", "613"];
    const cond_pluie_vergla = "511";
    const cond_orage = ["200", "201", "202", "210", "211", "212", "221", "230", "231", "232"];
    const cond_brouillard = ["701", "721", "741"];
    const cond_partiel_soleil = "803";
    const cond_plutot_soleil = ["801", "802"];
    const cond_soleil = 800;
    const cond_nuageux = 804;
    const jour = ['Dimanche', 'Lundi', 'Mardi', 'Mercredi', 'Jeudi', 'Vendredi', 'Samedi', 'Dimanche'];
    const cadre_now = document.getElementById('mia-meteo-cadre-now');
    const now_icone = document.getElementById('mia-meteo-now-icone');
    const now_temperature = document.getElementById('mia-meteo-now-temperature');
    const now_temps = document.getElementById('mia-meteo-now-temps');
    const lever_soleil = document.getElementById('mia-meteo-lever-soleil');
    const coucher_soleil = document.getElementById('mia-meteo-coucher-soleil');
    const now_temperature_mini = document.getElementById('mia-meteo-now-temperature-mini');
    const now_temperature_maxi = document.getElementById('mia-meteo-now-temperature-maxi');
    const now_vent_icone = document.getElementById('mia-meteo-now-vent-icone');
    const now_vent = document.getElementById('mia-meteo-now-vent');
    const now_pluie = document.getElementById('mia-meteo-now-pluie');
    const jour1_nom = document.getElementById('mia-meteo-jour1-nom');
    const jour1_icone = document.getElementById('mia-meteo-jour1-icone');
    const jour1_temperature = document.getElementById('mia-meteo-jour1-temperature');
    const jour2_nom = document.getElementById('mia-meteo-jour2-nom');
    const jour2_icone = document.getElementById('mia-meteo-jour2-icone');
    const jour2_temperature = document.getElementById('mia-meteo-jour2-temperature');
    const jour3_nom = document.getElementById('mia-meteo-jour3-nom');
    const jour3_icone = document.getElementById('mia-meteo-jour3-icone');
    const jour3_temperature = document.getElementById('mia-meteo-jour3-temperature');
    var nuit = new Boolean(false);
    var now = new Date();
  	var jour_numero = now.getDay();
    var heure = now.getHours().toString() + now.getMinutes().toString().padStart(2, '0');


    // Détermination si c'est le jour ou la nuit.
    if (Number(heure) > Number(valeur[3]) && Number(heure) < Number(valeur[4])) {
        nuit = false;
    } else {
        nuit = true;
    }


    // ******************** //
    // Cadre météo now      //
    // ******************** //

    // Icone et background.
    if (cond_pluie.includes(valeur[0]) === true) {

        if (nuit === true) {
            cadre_now.className = 'mia-meteo-cadre-now mia-meteo-now-nuit';
            now_icone.className = 'mia-meteo-now-icone wu wu-128 wu-white wu-night wu-rain';
        } else {
            cadre_now.className = 'mia-meteo-cadre-now mia-meteo-now-nuageux';
            now_icone.className = 'mia-meteo-now-icone wu wu-128 wu-white wu-day wu-rain';
        }

        now_temperature.className = 'mia-meteo-now-temperature mia-meteo-now-color-white';
        now_temps.className = 'mia-meteo-now-temps mia-meteo-now-color-white';

    } else if (cond_averse.includes(valeur[0]) === true) {

        if (nuit === true) {
            cadre_now.className = 'mia-meteo-cadre-now mia-meteo-now-nuit';
            now_icone.className = 'mia-meteo-now-icone wu wu-128 wu-white wu-night wu-chancerain';
        } else {
            cadre_now.className = 'mia-meteo-cadre-now mia-meteo-now-pluie';
            now_icone.className = 'mia-meteo-now-icone wu wu-128 wu-white wu-day wu-chancerain';
        }

        now_temperature.className = 'mia-meteo-now-temperature mia-meteo-now-color-white';
        now_temps.className = 'mia-meteo-now-temps mia-meteo-now-color-white';

    } else if (cond_crachin.includes(valeur[0]) === true) {

        if (nuit === true) {
            cadre_now.className = 'mia-meteo-cadre-now mia-meteo-now-nuit';
            now_icone.className = 'mia-meteo-now-icone wu wu-128 wu-white wu-night wu-flurries';
        } else {
            cadre_now.className = 'mia-meteo-cadre-now mia-meteo-now-nuageux';
            now_icone.className = 'mia-meteo-now-icone wu wu-128 wu-white wu-day wu-flurries';
        }

        now_temperature.className = 'mia-meteo-now-temperature mia-meteo-now-color-white';
        now_temps.className = 'mia-meteo-now-temps mia-meteo-now-color-white';

    } else if (cond_neige_fondue.includes(valeur[0]) === true) {

        if (nuit === true) {
            cadre_now.className = 'mia-meteo-cadre-now mia-meteo-now-nuit';
            now_icone.className = 'mia-meteo-now-icone wu wu-128 wu-white wu-night wu-chancesleet';
        } else {
            cadre_now.className = 'mia-meteo-cadre-now mia-meteo-now-nuageux';
            now_icone.className = 'mia-meteo-now-icone wu wu-128 wu-white wu-day wu-chancesleet';
        }

        now_temperature.className = 'mia-meteo-now-temperature mia-meteo-now-color-white';
        now_temps.className = 'mia-meteo-now-temps mia-meteo-now-color-white';

    } else if (cond_pluie_vergla.includes(valeur[0]) === true) {

        if (nuit === true) {
            cadre_now.className = 'mia-meteo-cadre-now mia-meteo-now-nuit';
            now_icone.className = 'mia-meteo-now-icone wu wu-128 wu-white wu-night wu-sleet';
        } else {
            cadre_now.className = 'mia-meteo-cadre-now mia-meteo-now-nuageux';
            now_icone.className = 'mia-meteo-now-icone wu wu-128 wu-white wu-day wu-sleet';
        }

        now_temperature.className = 'mia-meteo-now-temperature mia-meteo-now-color-white';
        now_temps.className = 'mia-meteo-now-temps mia-meteo-now-color-white';

    } else if (cond_neige.includes(valeur[0]) === true) {

        if (nuit === true) {
            cadre_now.className = 'mia-meteo-cadre-now mia-meteo-now-nuit';
            now_icone.className = 'mia-meteo-now-icone wu wu-128 wu-white wu-night wu-snow';
        } else {
            cadre_now.className = 'mia-meteo-cadre-now mia-meteo-now-neige';
            now_icone.className = 'mia-meteo-now-icone wu wu-128 wu-black wu-day wu-snow';
        }

        now_temperature.className = 'mia-meteo-now-temperature mia-meteo-now-color-blue';
        now_temps.className = 'mia-meteo-now-temps mia-meteo-now-color-blue';

    } else if (cond_orage.includes(valeur[0]) === true) {

        if (nuit === true) {
            cadre_now.className = 'mia-meteo-cadre-now mia-meteo-now-nuit';
            now_icone.className = 'mia-meteo-now-icone wu wu-128 wu-white wu-night wu-chancetstorms';
        } else {
            cadre_now.className = 'mia-meteo-cadre-now mia-meteo-now-orage';
            now_icone.className = 'mia-meteo-now-icone wu wu-128 wu-white wu-day wu-chancetstorms';
        }

        now_temperature.className = 'mia-meteo-now-temperature mia-meteo-now-color-white';
        now_temps.className = 'mia-meteo-now-temps mia-meteo-now-color-white';

    } else if (cond_partiel_soleil.includes(valeur[0]) === true) {

        if (nuit === true) {
            cadre_now.className = 'mia-meteo-cadre-now mia-meteo-now-nuit';
            now_icone.className = 'mia-meteo-now-icone wu wu-128 wu-white wu-night wu-partlysunny';
        } else {
            cadre_now.className = 'mia-meteo-cadre-now mia-meteo-now-nuageux';
            now_icone.className = 'mia-meteo-now-icone wu wu-128 wu-white wu-day wu-partlysunny';
        }

        now_temperature.className = 'mia-meteo-now-temperature mia-meteo-now-color-white';
        now_temps.className = 'mia-meteo-now-temps mia-meteo-now-color-white';

    } else if (cond_plutot_soleil.includes(valeur[0]) === true) {

        if (nuit === true) {
            cadre_now.className = 'mia-meteo-cadre-now mia-meteo-now-nuit';
            now_icone.className = 'mia-meteo-now-icone wu wu-128 wu-white wu-night wu-mostlysunny';
        } else {
            cadre_now.className = 'mia-meteo-cadre-now mia-meteo-now-soleil';
            now_icone.className = 'mia-meteo-now-icone wu wu-128 wu-white wu-day wu-mostlysunny';
        }

        now_temperature.className = 'mia-meteo-now-temperature mia-meteo-now-color-white';
        now_temps.className = 'mia-meteo-now-temps mia-meteo-now-color-white';

    } else if (cond_brouillard.includes(valeur[0]) === true) {

        if (nuit === true) {
            cadre_now.className = 'mia-meteo-cadre-now mia-meteo-now-nuit';
            now_icone.className = 'mia-meteo-now-icone wu wu-128 wu-white wu-night wu-fog';
        } else {
            cadre_now.className = 'mia-meteo-cadre-now mia-meteo-now-nuageux';
            now_icone.className = 'mia-meteo-now-icone wu wu-128 wu-white wu-day wu-fog';
        }

        now_temperature.className = 'mia-meteo-now-temperature mia-meteo-now-color-white';
        now_temps.className = 'mia-meteo-now-temps mia-meteo-now-color-white';

    } else if (valeur[0] == cond_soleil) {

        if (nuit === true) {
            cadre_now.className = 'mia-meteo-cadre-now mia-meteo-now-nuit';
            now_icone.className = 'mia-meteo-now-icone wu wu-128 wu-white wu-night wu-sunny';
        } else {
            cadre_now.className = 'mia-meteo-cadre-now mia-meteo-now-soleil';
            now_icone.className = 'mia-meteo-now-icone wu wu-128 wu-white wu-day wu-sunny';
        }

        now_temperature.className = 'mia-meteo-now-temperature mia-meteo-now-color-white';
        now_temps.className = 'mia-meteo-now-temps mia-meteo-now-color-white';

    } else if (valeur[0] == cond_nuageux) {

        if (nuit === true) {
            cadre_now.className = 'mia-meteo-cadre-now mia-meteo-now-nuit';
            now_icone.className = 'mia-meteo-now-icone wu wu-128 wu-white wu-night wu-cloudy';
        } else {
            cadre_now.className = 'mia-meteo-cadre-now mia-meteo-now-nuageux';
            now_icone.className = 'mia-meteo-now-icone wu wu-128 wu-white wu-day wu-cloudy';
        }

        now_temperature.className = 'mia-meteo-now-temperature mia-meteo-now-color-white';
        now_temps.className = 'mia-meteo-now-temps mia-meteo-now-color-white';

    } else {

        if (nuit === true) {
            cadre_now.className = 'mia-meteo-cadre-now mia-meteo-now-nuit';
            now_icone.className = 'mia-meteo-now-icone wu wu-128 wu-white wu-night wu-unknown';
        } else {
            cadre_now.className = 'mia-meteo-cadre-now mia-meteo-now-nuageux';
            now_icone.className = 'mia-meteo-now-icone wu wu-128 wu-white wu-day wu-unknown';
        }

        now_temperature.className = 'mia-meteo-now-temperature mia-meteo-now-color-white';
        now_temps.className = 'mia-meteo-now-temps mia-meteo-now-color-white';
    }


    // ******************** //
    // Cadre météo détail   //
    // ******************** //

    // Température et libellé condition.
    now_temperature.innerHTML = Math.round(valeur[2]) + '°';
    now_temps.innerHTML = valeur[1];

    // Lever et coucher du soleil.
    lever_soleil.innerHTML = '<i class="wi wi-sunrise"></i>&nbsp;' + (valeur[3].length == 3 ? valeur[3].substring(0, 1) + ':' + valeur[3].substring(1) : valeur[3].substring(0, 2) + ':' + valeur[3].substring(2));
    coucher_soleil.innerHTML = '<i class="wi wi-sunset"></i>&nbsp;' + (valeur[4].length == 3 ? valeur[4].substring(0, 1) + ':' + valeur[4].substring(1) : valeur[4].substring(0, 2) + ':' + valeur[4].substring(2));

    // Température mini et maxi.
    now_temperature_mini.innerHTML = '<i class="wi wi-thermometer-exterior"></i>&nbsp;' + valeur[5] + '°';
    now_temperature_maxi.innerHTML = '<i class="wi wi-thermometer"></i>&nbsp;' + valeur[6] + '°';

    // Vent et rafale.
    now_vent_icone.innerHTML = '<i class="mia-meteo-detail-icone-vent wi wi wi-wind from-' + valeur[7] + '-deg"></i>';
    now_vent.innerHTML = '&nbsp; <sup>' + valeur[8] + '</sup> / <sub>' + valeur[9];

    // Pluie actuelle et comulée journée.
    now_pluie.innerHTML = '&nbsp; <sup>' + valeur[10] + '</sup> / <sub>' + valeur[11];


    // ******************** //
    // Cadre prévision      //
    // ******************** //

    // Prévisions + 1.
    ((jour_numero + 1) > 7) ? jour1_nom.innerHTML = jour[jour_numero + 1 - 7] : jour1_nom.innerHTML = jour[jour_numero + 1];
    jour1_icone.className = Prevision_Icone(valeur[12]);
    jour1_temperature.innerHTML = Math.round(valeur[13]) + '° &ensp; ' + Math.round(valeur[14]) + '°';

    // Prévision + 2.
    ((jour_numero + 2) > 7) ? jour2_nom.innerHTML = jour[jour_numero + 2 - 7] : jour2_nom.innerHTML = jour[jour_numero + 2];
    jour2_icone.className = Prevision_Icone(valeur[15]);
    jour2_temperature.innerHTML = Math.round(valeur[16]) + '° &ensp; ' + Math.round(valeur[17]) + '°';

    // Prévision +3.
    ((jour_numero + 3) > 7) ? jour3_nom.innerHTML = jour[jour_numero + 3 - 7] : jour3_nom.innerHTML = jour[jour_numero + 3];
    jour3_icone.className = Prevision_Icone(valeur[18]);
    jour3_temperature.innerHTML = Math.round(valeur[19]) + '° &ensp; ' + Math.round(valeur[20]) + '°';

    // Fonction permettant de retourner l'icône en fonction du n° de condition pour les prévisions.
    function Prevision_Icone(meteo_condition) {

        if (cond_pluie.includes(meteo_condition) === true) {

            return 'wu wu-64 wu-white wu-day wu-rain';

        } else if (cond_averse.includes(meteo_condition) === true) {

            return 'wu wu-64 wu-white wu-day wu-chancerain';

        } else if (cond_crachin.includes(meteo_condition) === true) {

            return 'wu wu-64 wu-white wu-day wu-flurries';

        } else if (cond_neige_fondue.includes(meteo_condition) === true) {

            return 'wu wu-64 wu-white wu-day wu-chancesleet';

        } else if (cond_pluie_vergla.includes(meteo_condition) === true) {

            return 'wu wu-64 wu-white wu-day wu-sleet';

        } else if (cond_neige.includes(meteo_condition) === true) {

            return 'wu wu-64 wu-black wu-day wu-snow';

        } else if (cond_orage.includes(meteo_condition) === true) {

            return 'wu wu-64 wu-white wu-day wu-chancetstorms';

        } else if (cond_partiel_soleil.includes(meteo_condition) === true) {

            return 'wu wu-64 wu-white wu-day wu-partlysunny';

        } else if (cond_plutot_soleil.includes(meteo_condition) === true) {

            return 'wu wu-64 wu-white wu-day wu-mostlysunny';

        } else if (cond_brouillard.includes(meteo_condition) === true) {

            return 'wu wu-64 wu-white wu-day wu-fog';

        } else if (meteo_condition == cond_soleil) {

            return 'wu wu-64 wu-white wu-day wu-sunny';

        } else if (meteo_condition == cond_nuageux) {

            return 'wu wu-64 wu-white wu-day wu-cloudy';

        } else {

            return 'wu wu-64 wu-white wu-day wu-unknown';

        }
    }
}

Ce fichier n’est pas très commenté, si vous avez des questions n’hésitez pas.
A chaque update de l’affichage par Jeedom, ce script fait ceci :

  • Récupération des informations du virtuel dans un array
  • Détermine si nous sommes le jour ou la nuit (afin d’appliquer le bon background de la partie haute du widget)
  • En fonction des valeurs récupérés, affichage des icônes et background adéquat
  • Affichage des informations.

Les fichiers d’icones proviennent de :

Une fois tout cela créé / ajouté, il suffit de faire sur le design « Ajouter commande » et de sélectionner la commande du virtuel créé.

J’espère que ça été clair.
Si des questions, n’hesitez pas :slight_smile:

3 J'aimes

Merci infiniment !
Je vais pas bcp dormir cette nuit :smiley::smiley:

Xav

Désolé :stuck_out_tongue:

Une dernière question : comment tu gères le clic qui ouvre un nouveau cadre ?

Xav

Sur ton design en mode Edition, tu fais clique droit et Ajouter une zone.
Là tu adapte la taille de ta zone et sa position puis clique droit dessus et Paramètre d’affichage.

Dans spécifique tu sélectionné Widget au survol et tu décoche Afficher au survol (enfin moi je l’ai décoché pour n’avoir l’affichage qu’au clique).
Ensuite tu sélectionné l’équipement que tu souhaites.

J’essais dans la soirée de montrer un code CSS pour modifier l’affichage de l’équipement ainsi affiché.

Ah yes ! J’avais jamais utilisé cette méthode ! C’est top :slight_smile:
on en apprend tous les jours

Bonsoir,

Merci pour votre code.
j’ai ajouté dans le code pour avoir le design et le premier cadre cependant j’ai pas le design blanc et le cadre qui apparaissent.
j’ai du loupé un truc.

Comment faire pour avoir le design blanc avec les paramètres du css?

tu as bien activé la personnalisation avancée dans systèmes/Configuration/Interface ?
(Case à cocher à droite du bouton)

Xav