Bonjour,
Ce matin je souhaitais vous partager mon flow sur la gestion des volets sous Tuya avec Node-Red (un de plus vous allez me dire )
Tout d’abord, je remercie à nouveau la communauté qui m’a permis d’en arriver là.
1. Mes sources d’inspiration
Gestion Automatique des volets sous Node-Red (Azimuth)
Automatiser ses volets roulants en fonction du soleil été / hiver
Enfin:
Gestion des volets sous Node-Red en fonction du soleil, avec offsets paramétrables
2. Introduction
Tout d’abord une explication.
Tuya et HA ne sont pas synchronisé sur leur code d’état retour ce qui à pour conséquence une inversion des commandes lorsque HA pilote un volet Tuya.
En effet, Tuya renvoie 0 pour « volet fermé » là où HA attend 1 et inversement.
Par ailleurs, je me lançait dans Node-Red et je voulais voir mes limites.
De plus, je cherchais à comprendre le fonctionnement de Lovelace (sur ce point pas sûr du tout d’avoir été très loin quand je vois ce que vous faite. )
Je souhaitais me faire une doc pour y revenir plus tard (habitude de travail ) je me suis dit que la partager serait mieux.
Aller je me lance.
Les fonctions du flow
- Voici la liste des fonctions actuellement gérées
- Ouverture/Fermeture/Arrêt manuel du volet
- Gestion d’Ouverture/Fermeture en fonction de l’heure
- Gestion d’Ouverture/Fermeture en fonction du soleil avec possibilité de décalage (Offset)
- Gestion de la position du volet en fonction de l’Elévation et de l’Azimut du soleil dans le ciel
Les entités
Afin de mener à bien ce projet, j’ai dû créer une grande liste d’entité. Je vais vous les donner pour un volet charge à vous de dupliquer à votre convenance.
configuration.yaml
input_number: !include input_number.yaml
input_boolean: !include input_boolean.yaml
input_datetime: !include input_datetime.yaml
J’ai donc créé au même niveau que mon fichier configuration.yaml, les fichiers:
- input_number.yaml
- input_boolean.yaml
- input_datetime.yaml
Leur contenu
- input_number.yaml
# Gestion des pourcentages d'ouverture des volets roulants
volets_niveau_bureau:
name: volets_niveau_bureau
min: 0
max: 100
step: 1
mode: box
# Décalage d'ouverture volets
volets_auto_offset_ouvre_bureau:
name: Volets Offset bureau matin
min: -90
max: 90
step: 1
mode: slider
volets_auto_offset_ferme_bureau:
name: Offset bureau soir
min: -90
max: 90
step: 1
mode: slider
- input_boolean.yaml
# Entité permettant l'activation ou non d'une fonction
volets_auto_azimut_global:
name: volets_auto_azimut_global
icon: mdi:window-shutter
volets_auto_matin_global:
name: volets_auto_matin_global
icon: mdi:window-shutter
volets_auto_soir_global:
name: volets_auto_soir_global
icon: mdi:window-shutter
volets_auto_offset_matin_global:
name: volets_auto_offset_matin_global
icon: mdi:window-shutter
volets_auto_offset_soir_global:
name: volets_auto_offset_soir_global
icon: mdi:window-shutter
# Liste des boutons pilotant le mode auto des volets roulants
# Active ou pas la fonction d'ouverture auto du matin
volets_auto_matin_etat_bureau:
name: volets_auto_matin_etat_bureau
icon: mdi:window-shutter
# Toggle bascule entre Offset et heure
volets_auto_matin_toggle_bureau:
name: volets_auto_matin_toggle_bureau
icon: mdi:window-shutter
# Les mêmes pour le soir
volets_auto_soir_etat_bureau:
name: volets_auto_soir_etat_bureau
icon: mdi:window-shutter
volets_auto_soir_toggle_bureau:
name: volets_auto_soir_toggle_bureau
icon: mdi:window-shutter
# La gestion de la fonction azimut pour ce volet
volets_auto_azimut_bureau:
name: volets_auto_azimut_bureau
icon: mdi:window-shutter
# Liste des actionneurs montants pour volets roulants
volets_up_bureau:
name: volets_up_bureau
icon: mdi:arrow-up-bold
initial: off
# Liste des actionneurs descendants pour volets roulants
volets_down_bureau:
name: volets_down_bureau
icon: mdi:arrow-down-bold
initial: off
# Liste des actionneurs d'arrêt pour volets roulants
volets_stop_bureau:
name: volets_stop_bureau
icon: mdi:stop
initial: off
- input_datetime.yaml
#Entités donnant l'heure d'ouverture du volet
volets_auto_time_ouvre_bureau:
name: volets_auto_time_ouvre_bureau
has_date: false
has_time: true
#Entités donnant l'heure de fermeture du volet
volets_auto_time_ferme_bureau:
name: volets_auto_time_ferme_bureau
has_date: false
has_time: true
Vous remarquerez que j’ai normé les noms de variable. Si vous voulez que cela fonctionne vous ne devez modifier que le dernier tronçon du nom ici le nom du lieu « bureau ».
L’integration
Pour la gestion météorologique, j’ai utilisé l’intégration météo France.
L’interface
Pour la créer, j’ai utilisé le button-card de la communauté HACS.
views:
- title: test
path: test
layout:
width: 350
type: custom:vertical-layout
badges: []
cards:
- type: horizontal-stack
cards:
- type: vertical-stack
cards:
- type: custom:button-card
show_name: false
show_icon: false
color_type: blank-card
styles:
card:
- height: 30px
- width: 50px
- type: custom:button-card
show_name: false
show_icon: false
color_type: blank-card
styles:
card:
- height: 25px
- width: 50px
- type: custom:button-card
show_name: false
show_icon: false
color_type: blank-card
styles:
card:
- height: 25px
- width: 50px
- type: custom:button-card
show_name: false
show_icon: false
color_type: blank-card
styles:
card:
- height: 25px
- width: 50px
- type: custom:button-card
show_name: true
show_icon: false
styles:
card:
- height: 25px
- background-color: '#CCFFCC'
- color: rgb(38, 128, 199)
- width: 50px
name:
- color: rgb(0, 0, 0)
- font-weight: bold
- position: absolute
- left: 20px
tap_action:
action: none
show_state: false
name: '%'
hold_action:
action: none
- type: custom:button-card
show_name: true
show_icon: false
styles:
card:
- height: 124px
- background-color: rgb(255, 253, 179)
- width: 50px
name:
- color: rgb(0, 0, 0)
- font-weight: bold
- position: absolute
- left: 2px
- top: 55px
tap_action:
action: none
show_state: false
name: Matin
hold_action:
action: none
- type: custom:button-card
show_name: true
show_icon: false
styles:
card:
- height: 124px
- background-color: rgb(204, 255, 204)
- width: 50px
name:
- color: rgb(0, 0, 0)
- font-weight: bold
- position: absolute
- left: 10px
- top: 55px
tap_action:
action: toggle
show_state: false
entity: input_boolean.volets_auto_soir_global
state:
- value: 'on'
styles:
card:
- color: rgb(38, 128, 199)
- value: 'off'
styles:
card:
- color: '#FF0000'
name: Soir
hold_action:
action: none
- type: custom:button-card
show_name: true
show_icon: false
styles:
card:
- height: 25px
- background-color: rgb(204, 204, 255)
- width: 50px
name:
- font-weight: bold
- position: absolute
- left: 5px
- top: 5px
- font-size: 12px
tap_action:
action: toggle
show_state: false
entity: input_boolean.volets_auto_azimut_global
state:
- value: 'on'
styles:
card:
- color: rgb(0, 0, 0)
- value: 'off'
styles:
card:
- color: rgb(255, 0, 0)
name: Azimut
hold_action:
action: none
- type: vertical-stack
cards:
- type: custom:button-card
show_name: false
show_icon: true
icon: mdi:office-building
styles:
card:
- height: 30px
- width: 50px
icon:
- background-color: '#CCFFCC'
- color: rgb(38, 128, 199)
- width: 25px
- height: 25px
tap_action:
action: none
show_state: false
name: Bureau
hold_action:
action: none
- type: custom:button-card
icon: mdi:arrow-down-bold
show_name: false
show_icon: true
tap_action:
action: toggle
entity: input_boolean.volets_down_bureau
show_state: false
hold_action:
action: none
styles:
card:
- height: 25px
- width: 50px
icon:
- width: 25px
- height: 25px
- type: custom:button-card
icon: mdi:arrow-up-bold
show_name: false
show_icon: true
tap_action:
action: toggle
entity: input_boolean.volets_up_bureau
show_state: false
hold_action:
action: none
styles:
card:
- height: 25px
- width: 50px
icon:
- width: 25px
- height: 25px
- type: custom:button-card
icon: mdi:stop
show_name: false
show_icon: true
tap_action:
action: toggle
entity: input_boolean.volets_stop_bureau
show_state: false
hold_action:
action: none
styles:
card:
- height: 25px
- width: 50px
icon:
- width: 25px
- height: 25px
- type: custom:button-card
entity: input_number.volets_niveau_bureau
show_name: false
show_icon: false
show_state: true
styles:
card:
- height: 25px
- width: 50px
- background-color: '#CCFFCC'
- color: |
[[[
if (entity.state > 0 && entity.state < 100 )
return "rgb(0, 0, 0)";
else if (entity.state == 0)
return "'#FF0000'";
else
return '#00FF00';
]]]
state:
- font-size: 12px
- type: custom:button-card
show_name: false
show_icon: false
tap_action:
action: toggle
entity: input_boolean.volets_auto_matin_etat_bureau
show_state: true
hold_action:
action: none
styles:
card:
- height: 25px
- width: 50px
- background-color: rgb(255, 253, 179)
state:
- value: 'on'
styles:
card:
- color: '#00FF00'
state:
- font-size: 12px
- value: 'off'
styles:
card:
- color: '#FF0000'
state:
- font-size: 10px
- type: custom:button-card
variables:
my_entity: input_boolean.volets_auto_matin_toggle_bureau
show_name: true
show_icon: false
tap_action:
action: toggle
entity: '[[[ return variables.my_entity; ]]]'
show_state: false
name: |
[[[ if (entity.state == "on")
return "Offset";
else
return "Heure";
]]]
hold_action:
action: none
styles:
card:
- height: 25px
- width: 50px
- background-color: rgb(255, 253, 179)
name:
- font-size: 12px
state:
- value: 'on'
styles:
card:
- color: '#00FF00'
name:
- font-size: 12px
- value: 'off'
styles:
card:
- color: '#FF0000'
name:
- font-size: 12px
- type: custom:button-card
entity: input_datetime.volets_auto_time_ouvre_bureau
show_name: false
show_icon: false
show_state: true
styles:
card:
- height: 25px
- width: 50px
- background-color: rgb(255, 253, 179)
- color: rgb(0, 0, 0)
state:
- font-size: 12px
- type: custom:button-card
entity: input_number.volets_auto_offset_ouvre_bureau
show_name: false
show_icon: false
show_state: true
styles:
card:
- height: 25px
- width: 50px
- background-color: rgb(255, 253, 179)
- color: rgb(0, 0, 0)
state:
- font-size: 12px
- type: custom:button-card
show_name: false
show_icon: false
tap_action:
action: toggle
entity: input_boolean.volets_auto_soir_etat_bureau
show_state: true
hold_action:
action: none
styles:
card:
- height: 25px
- width: 50px
- background-color: rgb(204, 255, 204)
state:
- value: 'on'
styles:
card:
- color: '#00FF00'
state:
- font-size: 12px
- value: 'off'
styles:
card:
- color: '#FF0000'
state:
- font-size: 10px
- type: custom:button-card
variables:
my_entity: input_boolean.volets_auto_soir_toggle_bureau
show_name: true
show_icon: false
tap_action:
action: toggle
entity: '[[[ return variables.my_entity; ]]]'
show_state: false
name: |
[[[ if (entity.state == "on")
return "Offset";
else
return "Heure";
]]]
hold_action:
action: none
styles:
card:
- height: 25px
- width: 50px
- background-color: rgb(204, 255, 204)
name:
- font-size: 12px
state:
- value: 'on'
styles:
card:
- color: '#00FF00'
- value: 'off'
styles:
card:
- color: '#FF0000'
- type: custom:button-card
entity: input_datetime.volets_auto_time_ferme_bureau
show_name: false
show_icon: false
show_state: true
styles:
card:
- height: 25px
- width: 50px
- background-color: rgb(204, 255, 204)
state:
- color: rgb(0, 0, 0)
- font-size: 12px
- type: custom:button-card
entity: input_number.volets_auto_offset_ferme_bureau
show_name: false
show_icon: false
show_state: true
styles:
card:
- height: 25px
- width: 50px
- background-color: rgb(204, 255, 204)
state:
- color: rgb(0, 0, 0)
- font-size: 12px
- type: custom:button-card
show_name: false
show_icon: false
tap_action:
action: toggle
entity: input_boolean.volets_auto_azimut_bureau
show_state: true
hold_action:
action: none
styles:
card:
- height: 25px
- width: 50px
- background-color: rgb(204, 204, 255)
state:
- value: 'on'
styles:
card:
- color: '#00FF00'
state:
- font-size: 12px
- value: 'off'
styles:
card:
- color: '#FF0000'
state:
- font-size: 10px
- type: vertical-stack
cards:
- type: custom:button-card
show_name: false
show_icon: true
icon: mdi:table-chair
styles:
card:
- height: 30px
- width: 50px
icon:
- background-color: '#CCFFCC'
- color: rgb(38, 128, 199)
- width: 25px
- height: 25px
tap_action:
action: none
show_state: false
name: Bureau
hold_action:
action: none
- type: custom:button-card
icon: mdi:arrow-down-bold
show_name: false
show_icon: true
tap_action:
action: toggle
entity: input_boolean.volets_down_sam
show_state: false
hold_action:
action: none
styles:
card:
- height: 25px
- width: 50px
icon:
- width: 25px
- height: 25px
- type: custom:button-card
icon: mdi:arrow-up-bold
show_name: false
show_icon: true
tap_action:
action: toggle
entity: input_boolean.volets_up_sam
show_state: false
hold_action:
action: none
styles:
card:
- height: 25px
- width: 50px
icon:
- width: 25px
- height: 25px
- type: custom:button-card
icon: mdi:stop
show_name: false
show_icon: true
tap_action:
action: toggle
entity: input_boolean.volets_stop_sam
show_state: false
hold_action:
action: none
styles:
card:
- height: 25px
- width: 50px
icon:
- width: 25px
- height: 25px
- type: custom:button-card
entity: input_number.volets_niveau_sam
show_name: false
show_icon: false
show_state: true
styles:
card:
- height: 25px
- width: 50px
- background-color: '#CCFFCC'
- color: |
[[[
if (entity.state > 0 && entity.state < 100 )
return "rgb(0, 0, 0)";
else if (entity.state == 0)
return "'#FF0000'";
else
return '#00FF00';
]]]
state:
- font-size: 12px
- type: custom:button-card
show_name: false
show_icon: false
tap_action:
action: toggle
entity: input_boolean.volets_auto_matin_etat_sam
show_state: true
hold_action:
action: none
styles:
card:
- height: 25px
- width: 50px
- background-color: rgb(255, 253, 179)
state:
- value: 'on'
styles:
card:
- color: '#00FF00'
state:
- font-size: 12px
- value: 'off'
styles:
card:
- color: '#FF0000'
state:
- font-size: 10px
- type: custom:button-card
variables:
my_entity: input_boolean.volets_auto_matin_toggle_sam
show_name: true
show_icon: false
tap_action:
action: toggle
entity: '[[[ return variables.my_entity; ]]]'
show_state: false
name: |
[[[ if (entity.state == "on")
return "Offset";
else
return "Heure";
]]]
hold_action:
action: none
styles:
card:
- height: 25px
- width: 50px
- background-color: rgb(255, 253, 179)
name:
- font-size: 12px
state:
- value: 'on'
styles:
card:
- color: '#00FF00'
- value: 'off'
styles:
card:
- color: '#FF0000'
- type: custom:button-card
entity: input_datetime.volets_auto_time_ouvre_sam
show_name: false
show_icon: false
show_state: true
styles:
card:
- height: 25px
- width: 50px
- background-color: rgb(255, 253, 179)
- color: rgb(0, 0, 0)
state:
- font-size: 12px
- type: custom:button-card
entity: input_number.volets_auto_offset_ouvre_sam
show_name: false
show_icon: false
show_state: true
styles:
card:
- height: 25px
- width: 50px
- background-color: rgb(255, 253, 179)
- color: rgb(0, 0, 0)
state:
- font-size: 12px
- type: custom:button-card
show_name: false
show_icon: false
tap_action:
action: toggle
entity: input_boolean.volets_auto_soir_etat_sam
show_state: true
hold_action:
action: none
styles:
card:
- height: 25px
- width: 50px
- background-color: rgb(204, 255, 204)
state:
- value: 'on'
styles:
card:
- color: '#00FF00'
state:
- font-size: 12px
- value: 'off'
styles:
card:
- color: '#FF0000'
state:
- font-size: 10px
- type: custom:button-card
variables:
my_entity: input_boolean.volets_auto_soir_toggle_sam
show_name: true
show_icon: false
tap_action:
action: toggle
entity: '[[[ return variables.my_entity; ]]]'
show_state: false
name: |
[[[ if (entity.state == "on")
return "Offset";
else
return "Heure";
]]]
hold_action:
action: none
styles:
card:
- height: 25px
- width: 50px
- background-color: rgb(204, 255, 204)
name:
- font-size: 12px
state:
- value: 'on'
styles:
card:
- color: '#00FF00'
- value: 'off'
styles:
card:
- color: '#FF0000'
- type: custom:button-card
entity: input_datetime.volets_auto_time_ferme_sam
show_name: false
show_icon: false
show_state: true
styles:
card:
- height: 25px
- width: 50px
- background-color: rgb(204, 255, 204)
state:
- color: rgb(0, 0, 0)
- font-size: 12px
- type: custom:button-card
entity: input_number.volets_auto_offset_ferme_sam
show_name: false
show_icon: false
show_state: true
styles:
card:
- height: 25px
- width: 50px
- background-color: rgb(204, 255, 204)
state:
- color: rgb(0, 0, 0)
- font-size: 12px
- type: custom:button-card
show_name: false
show_icon: false
tap_action:
action: toggle
entity: input_boolean.volets_auto_azimut_sam
show_state: true
hold_action:
action: none
styles:
card:
- height: 25px
- width: 50px
- background-color: rgb(204, 204, 255)
state:
- value: 'on'
styles:
card:
- color: '#00FF00'
state:
- font-size: 12px
- value: 'off'
styles:
card:
- color: '#FF0000'
state:
- font-size: 10px
- type: vertical-stack
cards:
- type: custom:button-card
show_name: false
show_icon: true
icon: mdi:sofa
styles:
card:
- height: 30px
- width: 50px
icon:
- background-color: '#CCFFCC'
- color: rgb(38, 128, 199)
- width: 25px
- height: 25px
tap_action:
action: none
show_state: false
name: Bureau
hold_action:
action: none
- type: custom:button-card
icon: mdi:arrow-down-bold
show_name: false
show_icon: true
tap_action:
action: toggle
entity: input_boolean.volets_down_salon
show_state: false
hold_action:
action: none
styles:
card:
- height: 25px
- width: 50px
icon:
- width: 25px
- height: 25px
- type: custom:button-card
icon: mdi:arrow-up-bold
show_name: false
show_icon: true
tap_action:
action: toggle
entity: input_boolean.volets_up_salon
show_state: false
hold_action:
action: none
styles:
card:
- height: 25px
- width: 50px
icon:
- width: 25px
- height: 25px
- type: custom:button-card
icon: mdi:stop
show_name: false
show_icon: true
tap_action:
action: toggle
entity: input_boolean.volets_stop_salon
show_state: false
hold_action:
action: none
styles:
card:
- height: 25px
- width: 50px
icon:
- width: 25px
- height: 25px
- type: custom:button-card
entity: input_number.volets_niveau_salon
show_name: false
show_icon: false
show_state: true
styles:
card:
- height: 25px
- width: 50px
- background-color: '#CCFFCC'
- color: |
[[[
if (entity.state > 0 && entity.state < 100 )
return "rgb(0, 0, 0)";
else if (entity.state == 0)
return "'#FF0000'";
else
return '#00FF00';
]]]
state:
- font-size: 12px
- type: custom:button-card
show_name: false
show_icon: false
tap_action:
action: toggle
entity: input_boolean.volets_auto_matin_etat_salon
show_state: true
hold_action:
action: none
styles:
card:
- height: 25px
- width: 50px
- background-color: rgb(255, 253, 179)
state:
- value: 'on'
styles:
card:
- color: '#00FF00'
state:
- font-size: 12px
- value: 'off'
styles:
card:
- color: '#FF0000'
state:
- font-size: 10px
- type: custom:button-card
variables:
my_entity: input_boolean.volets_auto_matin_toggle_salon
show_name: true
show_icon: false
tap_action:
action: toggle
entity: '[[[ return variables.my_entity; ]]]'
show_state: false
name: |
[[[ if (entity.state == "on")
return "Offset";
else
return "Heure";
]]]
hold_action:
action: none
styles:
card:
- height: 25px
- width: 50px
- background-color: rgb(255, 253, 179)
name:
- font-size: 12px
state:
- value: 'on'
styles:
card:
- color: '#00FF00'
- value: 'off'
styles:
card:
- color: '#FF0000'
- type: custom:button-card
entity: input_datetime.volets_auto_time_ouvre_salon
show_name: false
show_icon: false
show_state: true
styles:
card:
- height: 25px
- width: 50px
- background-color: rgb(255, 253, 179)
- color: rgb(0, 0, 0)
state:
- font-size: 12px
- type: custom:button-card
entity: input_number.volets_auto_offset_ouvre_salon
show_name: false
show_icon: false
show_state: true
styles:
card:
- height: 25px
- width: 50px
- background-color: rgb(255, 253, 179)
- color: rgb(0, 0, 0)
state:
- font-size: 12px
- type: custom:button-card
show_name: false
show_icon: false
tap_action:
action: toggle
entity: input_boolean.volets_auto_soir_etat_salon
show_state: true
hold_action:
action: none
styles:
card:
- height: 25px
- width: 50px
- background-color: rgb(204, 255, 204)
state:
- value: 'on'
styles:
card:
- color: '#00FF00'
state:
- font-size: 12px
- value: 'off'
styles:
card:
- color: '#FF0000'
state:
- font-size: 10px
- type: custom:button-card
variables:
my_entity: input_boolean.volets_auto_soir_toggle_salon
show_name: true
show_icon: false
tap_action:
action: toggle
entity: '[[[ return variables.my_entity; ]]]'
show_state: false
name: |
[[[ if (entity.state == "on")
return "Offset";
else
return "Heure";
]]]
hold_action:
action: none
styles:
card:
- height: 25px
- width: 50px
- background-color: rgb(204, 255, 204)
name:
- font-size: 12px
state:
- value: 'on'
styles:
card:
- color: '#00FF00'
- value: 'off'
styles:
card:
- color: '#FF0000'
- type: custom:button-card
entity: input_datetime.volets_auto_time_ferme_salon
show_name: false
show_icon: false
show_state: true
styles:
card:
- height: 25px
- width: 50px
- background-color: rgb(204, 255, 204)
state:
- color: rgb(0, 0, 0)
- font-size: 12px
- type: custom:button-card
entity: input_number.volets_auto_offset_ferme_salon
show_name: false
show_icon: false
show_state: true
styles:
card:
- height: 25px
- width: 50px
- background-color: rgb(204, 255, 204)
state:
- color: rgb(0, 0, 0)
- font-size: 12px
- type: custom:button-card
show_name: false
show_icon: false
tap_action:
action: toggle
entity: input_boolean.volets_auto_azimut_salon
show_state: true
hold_action:
action: none
styles:
card:
- height: 25px
- width: 50px
- background-color: rgb(204, 204, 255)
state:
- value: 'on'
styles:
card:
- color: '#00FF00'
state:
- font-size: 12px
- value: 'off'
styles:
card:
- color: '#FF0000'
state:
- font-size: 10px
- type: vertical-stack
cards:
- type: custom:button-card
show_name: false
show_icon: true
icon: mdi:water-pump
styles:
card:
- height: 30px
- width: 50px
icon:
- background-color: '#CCFFCC'
- color: rgb(38, 128, 199)
- width: 25px
- height: 25px
tap_action:
action: none
show_state: false
name: Bureau
hold_action:
action: none
- type: custom:button-card
icon: mdi:arrow-down-bold
show_name: false
show_icon: true
tap_action:
action: toggle
entity: input_boolean.volets_down_cuisine
show_state: false
hold_action:
action: none
styles:
card:
- height: 25px
- width: 50px
icon:
- width: 25px
- height: 25px
- type: custom:button-card
icon: mdi:arrow-up-bold
show_name: false
show_icon: true
tap_action:
action: toggle
entity: input_boolean.volets_up_cuisine
show_state: false
hold_action:
action: none
styles:
card:
- height: 25px
- width: 50px
icon:
- width: 25px
- height: 25px
- type: custom:button-card
icon: mdi:stop
show_name: false
show_icon: true
tap_action:
action: toggle
entity: input_boolean.volets_stop_cuisine
show_state: false
hold_action:
action: none
styles:
card:
- height: 25px
- width: 50px
icon:
- width: 25px
- height: 25px
- type: custom:button-card
entity: input_number.volets_niveau_cuisine
show_name: false
show_icon: false
show_state: true
styles:
card:
- height: 25px
- width: 50px
- background-color: '#CCFFCC'
- color: |
[[[
if (entity.state > 0 && entity.state < 100 )
return "rgb(0, 0, 0)";
else if (entity.state == 0)
return "'#FF0000'";
else
return '#00FF00';
]]]
state:
- font-size: 12px
- type: custom:button-card
show_name: false
show_icon: false
tap_action:
action: toggle
entity: input_boolean.volets_auto_matin_etat_cuisine
show_state: true
hold_action:
action: none
styles:
card:
- height: 25px
- width: 50px
- background-color: rgb(255, 253, 179)
state:
- value: 'on'
styles:
card:
- color: '#00FF00'
state:
- font-size: 12px
- value: 'off'
styles:
card:
- color: '#FF0000'
state:
- font-size: 10px
- type: custom:button-card
variables:
my_entity: input_boolean.volets_auto_matin_toggle_cuisine
show_name: true
show_icon: false
tap_action:
action: toggle
entity: '[[[ return variables.my_entity; ]]]'
show_state: false
name: |
[[[ if (entity.state == "on")
return "Offset";
else
return "Heure";
]]]
hold_action:
action: none
styles:
card:
- height: 25px
- width: 50px
- background-color: rgb(255, 253, 179)
name:
- font-size: 12px
state:
- value: 'on'
styles:
card:
- color: '#00FF00'
- value: 'off'
styles:
card:
- color: '#FF0000'
- type: custom:button-card
entity: input_datetime.volets_auto_time_ouvre_cuisine
show_name: false
show_icon: false
show_state: true
styles:
card:
- height: 25px
- width: 50px
- background-color: rgb(255, 253, 179)
- color: rgb(0, 0, 0)
state:
- font-size: 12px
- type: custom:button-card
entity: input_number.volets_auto_offset_ouvre_cuisine
show_name: false
show_icon: false
show_state: true
styles:
card:
- height: 25px
- width: 50px
- background-color: rgb(255, 253, 179)
- color: rgb(0, 0, 0)
state:
- font-size: 12px
- type: custom:button-card
show_name: false
show_icon: false
tap_action:
action: toggle
entity: input_boolean.volets_auto_soir_etat_cuisine
show_state: true
hold_action:
action: none
styles:
card:
- height: 25px
- width: 50px
- background-color: rgb(204, 255, 204)
state:
- value: 'on'
styles:
card:
- color: '#00FF00'
state:
- font-size: 12px
- value: 'off'
styles:
card:
- color: '#FF0000'
state:
- font-size: 10px
- type: custom:button-card
variables:
my_entity: input_boolean.volets_auto_soir_toggle_cuisine
show_name: true
show_icon: false
tap_action:
action: toggle
entity: '[[[ return variables.my_entity; ]]]'
show_state: false
name: |
[[[ if (entity.state == "on")
return "Offset";
else
return "Heure";
]]]
hold_action:
action: none
styles:
card:
- height: 25px
- width: 50px
- background-color: rgb(204, 255, 204)
name:
- font-size: 12px
state:
- value: 'on'
styles:
card:
- color: '#00FF00'
- value: 'off'
styles:
card:
- color: '#FF0000'
- type: custom:button-card
entity: input_datetime.volets_auto_time_ferme_cuisine
show_name: false
show_icon: false
show_state: true
styles:
card:
- height: 25px
- width: 50px
- background-color: rgb(204, 255, 204)
state:
- color: rgb(0, 0, 0)
- font-size: 12px
- type: custom:button-card
entity: input_number.volets_auto_offset_ferme_cuisine
show_name: false
show_icon: false
show_state: true
styles:
card:
- height: 25px
- width: 50px
- background-color: rgb(204, 255, 204)
state:
- color: rgb(0, 0, 0)
- font-size: 12px
- type: custom:button-card
show_name: false
show_icon: false
tap_action:
action: toggle
entity: input_boolean.volets_auto_azimut_cuisine
show_state: true
hold_action:
action: none
styles:
card:
- height: 25px
- width: 50px
- background-color: rgb(204, 204, 255)
state:
- value: 'on'
styles:
card:
- color: '#00FF00'
state:
- font-size: 12px
- value: 'off'
styles:
card:
- color: '#FF0000'
state:
- font-size: 10px
- type: vertical-stack
cards:
- type: custom:button-card
show_name: true
show_icon: true
icon: mdi:bed
styles:
card:
- height: 30px
- width: 50px
icon:
- height: 50px
- background-color: '#CCFFCC'
- color: rgb(38, 128, 199)
- width: 80px
name:
- font-size: 10px
tap_action:
action: none
show_state: false
name: CH1
hold_action:
action: none
- type: custom:button-card
icon: mdi:arrow-down-bold
show_name: false
show_icon: true
tap_action:
action: toggle
entity: input_boolean.volets_down_ch1
show_state: false
hold_action:
action: none
styles:
card:
- height: 25px
- width: 50px
icon:
- width: 25px
- height: 25px
- type: custom:button-card
icon: mdi:arrow-up-bold
show_name: false
show_icon: true
tap_action:
action: toggle
entity: input_boolean.volets_up_ch1
show_state: false
hold_action:
action: none
styles:
card:
- height: 25px
- width: 50px
icon:
- width: 25px
- height: 25px
- type: custom:button-card
icon: mdi:stop
show_name: false
show_icon: true
tap_action:
action: toggle
entity: input_boolean.volets_stop_ch1
show_state: false
hold_action:
action: none
styles:
card:
- height: 25px
- width: 50px
icon:
- width: 25px
- height: 25px
- type: custom:button-card
entity: input_number.volets_niveau_ch1
show_name: false
show_icon: false
show_state: true
styles:
card:
- height: 25px
- width: 50px
- background-color: '#CCFFCC'
- color: |
[[[
if (entity.state > 0 && entity.state < 100 )
return "rgb(0, 0, 0)";
else if (entity.state == 0)
return "'#FF0000'";
else
return '#00FF00';
]]]
state:
- font-size: 12px
- type: custom:button-card
show_name: false
show_icon: false
tap_action:
action: toggle
entity: input_boolean.volets_auto_matin_etat_ch1
show_state: true
hold_action:
action: none
styles:
card:
- height: 25px
- width: 50px
- background-color: rgb(255, 253, 179)
state:
- value: 'on'
styles:
card:
- color: '#00FF00'
state:
- font-size: 12px
- value: 'off'
styles:
card:
- color: '#FF0000'
state:
- font-size: 10px
- type: custom:button-card
variables:
my_entity: input_boolean.volets_auto_matin_toggle_ch1
show_name: true
show_icon: false
tap_action:
action: toggle
entity: '[[[ return variables.my_entity; ]]]'
show_state: false
name: |
[[[ if (entity.state == "on")
return "Offset";
else
return "Heure";
]]]
hold_action:
action: none
styles:
card:
- height: 25px
- width: 50px
- background-color: rgb(255, 253, 179)
name:
- font-size: 12px
state:
- value: 'on'
styles:
card:
- color: '#00FF00'
- value: 'off'
styles:
card:
- color: '#FF0000'
- type: custom:button-card
entity: input_datetime.volets_auto_time_ouvre_ch1
show_name: false
show_icon: false
show_state: true
styles:
card:
- height: 25px
- width: 50px
- background-color: rgb(255, 253, 179)
- color: rgb(0, 0, 0)
state:
- font-size: 12px
- type: custom:button-card
entity: input_number.volets_auto_offset_ouvre_ch1
show_name: false
show_icon: false
show_state: true
styles:
card:
- height: 25px
- width: 50px
- background-color: rgb(255, 253, 179)
- color: rgb(0, 0, 0)
state:
- font-size: 12px
- type: custom:button-card
show_name: false
show_icon: false
tap_action:
action: toggle
entity: input_boolean.volets_auto_soir_etat_ch1
show_state: true
hold_action:
action: none
styles:
card:
- height: 25px
- width: 50px
- background-color: rgb(204, 255, 204)
state:
- value: 'on'
styles:
card:
- color: '#00FF00'
state:
- font-size: 12px
- value: 'off'
styles:
card:
- color: '#FF0000'
state:
- font-size: 10px
- type: custom:button-card
variables:
my_entity: input_boolean.volets_auto_soir_toggle_ch1
show_name: true
show_icon: false
tap_action:
action: toggle
entity: '[[[ return variables.my_entity; ]]]'
show_state: false
name: |
[[[ if (entity.state == "on")
return "Offset";
else
return "Heure";
]]]
hold_action:
action: none
styles:
card:
- height: 25px
- width: 50px
- background-color: rgb(204, 255, 204)
name:
- font-size: 12px
state:
- value: 'on'
styles:
card:
- color: '#00FF00'
- value: 'off'
styles:
card:
- color: '#FF0000'
- type: custom:button-card
entity: input_datetime.volets_auto_time_ferme_ch1
show_name: false
show_icon: false
show_state: true
styles:
card:
- height: 25px
- width: 50px
- background-color: rgb(204, 255, 204)
state:
- color: rgb(0, 0, 0)
- font-size: 12px
- type: custom:button-card
entity: input_number.volets_auto_offset_ferme_ch1
show_name: false
show_icon: false
show_state: true
styles:
card:
- height: 25px
- width: 50px
- background-color: rgb(204, 255, 204)
state:
- color: rgb(0, 0, 0)
- font-size: 12px
- type: custom:button-card
show_name: false
show_icon: false
tap_action:
action: toggle
entity: input_boolean.volets_auto_azimut_ch1
show_state: true
hold_action:
action: none
styles:
card:
- height: 25px
- width: 50px
- background-color: rgb(204, 204, 255)
state:
- value: 'on'
styles:
card:
- color: '#00FF00'
state:
- font-size: 12px
- value: 'off'
styles:
card:
- color: '#FF0000'
state:
- font-size: 10px
- type: vertical-stack
cards:
- type: custom:button-card
show_name: true
show_icon: true
icon: mdi:bed
styles:
card:
- height: 30px
- width: 50px
icon:
- height: 50px
- background-color: '#CCFFCC'
- color: rgb(38, 128, 199)
- width: 80px
name:
- font-size: 10px
tap_action:
action: none
show_state: false
name: CH2
hold_action:
action: none
- type: custom:button-card
icon: mdi:arrow-down-bold
show_name: false
show_icon: true
tap_action:
action: toggle
entity: input_boolean.volets_down_ch2
show_state: false
hold_action:
action: none
styles:
card:
- height: 25px
- width: 50px
icon:
- width: 25px
- height: 25px
- type: custom:button-card
icon: mdi:arrow-up-bold
show_name: false
show_icon: true
tap_action:
action: toggle
entity: input_boolean.volets_up_ch2
show_state: false
hold_action:
action: none
styles:
card:
- height: 25px
- width: 50px
icon:
- width: 25px
- height: 25px
- type: custom:button-card
icon: mdi:stop
show_name: false
show_icon: true
tap_action:
action: toggle
entity: input_boolean.volets_stop_ch2
show_state: false
hold_action:
action: none
styles:
card:
- height: 25px
- width: 50px
icon:
- width: 25px
- height: 25px
- type: custom:button-card
entity: input_number.volets_niveau_ch2
show_name: false
show_icon: false
show_state: true
styles:
card:
- height: 25px
- width: 50px
- background-color: '#CCFFCC'
- color: |
[[[
if (entity.state > 0 && entity.state < 100 )
return "rgb(0, 0, 0)";
else if (entity.state == 0)
return "'#FF0000'";
else
return '#00FF00';
]]]
state:
- font-size: 12px
- type: custom:button-card
show_name: false
show_icon: false
tap_action:
action: toggle
entity: input_boolean.volets_auto_matin_etat_ch2
show_state: true
hold_action:
action: none
styles:
card:
- height: 25px
- width: 50px
- background-color: rgb(255, 253, 179)
state:
- value: 'on'
styles:
card:
- color: '#00FF00'
state:
- font-size: 12px
- value: 'off'
styles:
card:
- color: '#FF0000'
state:
- font-size: 10px
- type: custom:button-card
variables:
my_entity: input_boolean.volets_auto_matin_toggle_ch2
show_name: true
show_icon: false
tap_action:
action: toggle
entity: '[[[ return variables.my_entity; ]]]'
show_state: false
name: |
[[[ if (entity.state == "on")
return "Offset";
else
return "Heure";
]]]
hold_action:
action: none
styles:
card:
- height: 25px
- width: 50px
- background-color: rgb(255, 253, 179)
name:
- font-size: 12px
state:
- value: 'on'
styles:
card:
- color: '#00FF00'
- value: 'off'
styles:
card:
- color: '#FF0000'
- type: custom:button-card
entity: input_datetime.volets_auto_time_ouvre_ch2
show_name: false
show_icon: false
show_state: true
styles:
card:
- height: 25px
- width: 50px
- background-color: rgb(255, 253, 179)
- color: rgb(0, 0, 0)
state:
- font-size: 12px
- type: custom:button-card
entity: input_number.volets_auto_offset_ouvre_ch2
show_name: false
show_icon: false
show_state: true
styles:
card:
- height: 25px
- width: 50px
- background-color: rgb(255, 253, 179)
- color: rgb(0, 0, 0)
state:
- font-size: 12px
- type: custom:button-card
show_name: false
show_icon: false
tap_action:
action: toggle
entity: input_boolean.volets_auto_soir_etat_ch2
show_state: true
hold_action:
action: none
styles:
card:
- height: 25px
- width: 50px
- background-color: rgb(204, 255, 204)
state:
- value: 'on'
styles:
card:
- color: '#00FF00'
state:
- font-size: 12px
- value: 'off'
styles:
card:
- color: '#FF0000'
state:
- font-size: 10px
- type: custom:button-card
variables:
my_entity: input_boolean.volets_auto_soir_toggle_ch2
show_name: true
show_icon: false
tap_action:
action: toggle
entity: '[[[ return variables.my_entity; ]]]'
show_state: false
name: |
[[[ if (entity.state == "on")
return "Offset";
else
return "Heure";
]]]
hold_action:
action: none
styles:
card:
- height: 25px
- width: 50px
- background-color: rgb(204, 255, 204)
name:
- font-size: 12px
state:
- value: 'on'
styles:
card:
- color: '#00FF00'
- value: 'off'
styles:
card:
- color: '#FF0000'
- type: custom:button-card
entity: input_datetime.volets_auto_time_ferme_ch2
show_name: false
show_icon: false
show_state: true
styles:
card:
- height: 25px
- width: 50px
- background-color: rgb(204, 255, 204)
state:
- color: rgb(0, 0, 0)
- font-size: 12px
- type: custom:button-card
entity: input_number.volets_auto_offset_ferme_ch2
show_name: false
show_icon: false
show_state: true
styles:
card:
- height: 25px
- width: 50px
- background-color: rgb(204, 255, 204)
state:
- color: rgb(0, 0, 0)
- font-size: 12px
- type: custom:button-card
show_name: false
show_icon: false
tap_action:
action: toggle
entity: input_boolean.volets_auto_azimut_ch2
show_state: true
hold_action:
action: none
styles:
card:
- height: 25px
- width: 50px
- background-color: rgb(204, 204, 255)
state:
- value: 'on'
styles:
card:
- color: '#00FF00'
state:
- font-size: 12px
- value: 'off'
styles:
card:
- color: '#FF0000'
state:
- font-size: 10px
- type: vertical-stack
cards:
- type: custom:button-card
show_name: true
show_icon: true
icon: mdi:bed
styles:
card:
- height: 30px
- width: 50px
icon:
- height: 50px
- background-color: '#CCFFCC'
- color: rgb(38, 128, 199)
- width: 80px
name:
- font-size: 10px
tap_action:
action: none
show_state: false
name: CH3
hold_action:
action: none
- type: custom:button-card
icon: mdi:arrow-down-bold
show_name: false
show_icon: true
tap_action:
action: toggle
entity: input_boolean.volets_down_ch3
show_state: false
hold_action:
action: none
styles:
card:
- height: 25px
- width: 50px
icon:
- width: 25px
- height: 25px
- type: custom:button-card
icon: mdi:arrow-up-bold
show_name: false
show_icon: true
tap_action:
action: toggle
entity: input_boolean.volets_up_ch3
show_state: false
hold_action:
action: none
styles:
card:
- height: 25px
- width: 50px
icon:
- width: 25px
- height: 25px
- type: custom:button-card
icon: mdi:stop
show_name: false
show_icon: true
tap_action:
action: toggle
entity: input_boolean.volets_stop_ch3
show_state: false
hold_action:
action: none
styles:
card:
- height: 25px
- width: 50px
icon:
- width: 25px
- height: 25px
- type: custom:button-card
entity: input_number.volets_niveau_ch3
show_name: false
show_icon: false
show_state: true
styles:
card:
- height: 25px
- width: 50px
- background-color: '#CCFFCC'
- color: |
[[[
if (entity.state > 0 && entity.state < 100 )
return "rgb(0, 0, 0)";
else if (entity.state == 0)
return "'#FF0000'";
else
return '#00FF00';
]]]
state:
- font-size: 12px
- type: custom:button-card
show_name: false
show_icon: false
tap_action:
action: toggle
entity: input_boolean.volets_auto_matin_etat_ch3
show_state: true
hold_action:
action: none
styles:
card:
- height: 25px
- width: 50px
- background-color: rgb(255, 253, 179)
state:
- value: 'on'
styles:
card:
- color: '#00FF00'
state:
- font-size: 12px
- value: 'off'
styles:
card:
- color: '#FF0000'
state:
- font-size: 10px
- type: custom:button-card
variables:
my_entity: input_boolean.volets_auto_matin_toggle_ch3
show_name: true
show_icon: false
tap_action:
action: toggle
entity: '[[[ return variables.my_entity; ]]]'
show_state: false
name: |
[[[ if (entity.state == "on")
return "Offset";
else
return "Heure";
]]]
hold_action:
action: none
styles:
card:
- height: 25px
- width: 50px
- background-color: rgb(255, 253, 179)
name:
- font-size: 12px
state:
- value: 'on'
styles:
card:
- color: '#00FF00'
- value: 'off'
styles:
card:
- color: '#FF0000'
- type: custom:button-card
entity: input_datetime.volets_auto_time_ouvre_ch3
show_name: false
show_icon: false
show_state: true
styles:
card:
- height: 25px
- width: 50px
- background-color: rgb(255, 253, 179)
- color: rgb(0, 0, 0)
state:
- font-size: 12px
- type: custom:button-card
entity: input_number.volets_auto_offset_ouvre_ch3
show_name: false
show_icon: false
show_state: true
styles:
card:
- height: 25px
- width: 50px
- background-color: rgb(255, 253, 179)
- color: rgb(0, 0, 0)
state:
- font-size: 12px
- type: custom:button-card
show_name: false
show_icon: false
tap_action:
action: toggle
entity: input_boolean.volets_auto_soir_etat_ch3
show_state: true
hold_action:
action: none
styles:
card:
- height: 25px
- width: 50px
- background-color: rgb(204, 255, 204)
state:
- value: 'on'
styles:
card:
- color: '#00FF00'
state:
- font-size: 12px
- value: 'off'
styles:
card:
- color: '#FF0000'
state:
- font-size: 10px
- type: custom:button-card
variables:
my_entity: input_boolean.volets_auto_soir_toggle_ch3
show_name: true
show_icon: false
tap_action:
action: toggle
entity: '[[[ return variables.my_entity; ]]]'
show_state: false
name: |
[[[ if (entity.state == "on")
return "Offset";
else
return "Heure";
]]]
hold_action:
action: none
styles:
card:
- height: 25px
- width: 50px
- background-color: rgb(204, 255, 204)
name:
- font-size: 12px
state:
- value: 'on'
styles:
card:
- color: '#00FF00'
- value: 'off'
styles:
card:
- color: '#FF0000'
- type: custom:button-card
entity: input_datetime.volets_auto_time_ferme_ch3
show_name: false
show_icon: false
show_state: true
styles:
card:
- height: 25px
- width: 50px
- background-color: rgb(204, 255, 204)
state:
- color: rgb(0, 0, 0)
- font-size: 12px
- type: custom:button-card
entity: input_number.volets_auto_offset_ferme_ch3
show_name: false
show_icon: false
show_state: true
styles:
card:
- height: 25px
- width: 50px
- background-color: rgb(204, 255, 204)
state:
- color: rgb(0, 0, 0)
- font-size: 12px
- type: custom:button-card
show_name: false
show_icon: false
tap_action:
action: toggle
entity: input_boolean.volets_auto_azimut_ch3
show_state: true
hold_action:
action: none
styles:
card:
- height: 25px
- width: 50px
- background-color: rgb(204, 204, 255)
state:
- value: 'on'
styles:
card:
- color: '#00FF00'
state:
- font-size: 12px
- value: 'off'
styles:
card:
- color: '#FF0000'
state:
- font-size: 10px
- type: vertical-stack
cards:
- type: custom:button-card
show_name: true
entity: sensor.sun_next_rising
name: Levé du soleil
show_icon: false
tap_action:
action: none
show_state: true
hold_action:
action: none
styles:
card:
- height: 30px
grid:
- grid-template-areas: '"n s"'
- grid-template-columns: 200px 200px
- grid-template-rows: min-content min-content
state:
- font-size: 12px
- align-items: start
- margin-top: '-10px'
name:
- font-size: 12px
- align-items: start
- margin-top: '-10px'
state:
- name: '[[[return entity.state]]]'
- type: custom:button-card
show_name: true
entity: sensor.sun_next_setting
name: Couché du soleil
show_icon: false
tap_action:
action: none
show_state: true
hold_action:
action: none
styles:
card:
- height: 35px
grid:
- grid-template-areas: '"n s"'
- grid-template-columns: 200px 200px
- grid-template-rows: min-content min-content
state:
- font-size: 12px
- align-items: start
- margin-top: '-10px'
name:
- font-size: 12px
- align-items: start
- margin-top: '-10px'
state:
- name: '[[[return entity.state]]]'
- type: custom:button-card
show_name: true
entity: sensor.lavaur_daily_original_condition
name: Météo Lavaur
show_icon: false
tap_action:
action: none
show_state: true
hold_action:
action: none
styles:
card:
- height: 35px
grid:
- grid-template-areas: '"n s"'
- grid-template-columns: 200px 200px
- grid-template-rows: min-content min-content
state:
- font-size: 12px
- align-items: start
- margin-top: '-10px'
name:
- font-size: 12px
- align-items: start
- margin-top: '-10px'
state:
- name: '[[[return entity.state]]]'
Le flow
[{"id":"d8d288c742b5c81b","type":"subflow","name":"API Tuya iot","info":"# Gestion des APIs TUYA Iot\r\n\r\nAfin de faire fonctionner ce subflow, il faut lui passer le message de structure:\r\n\r\nmsg.tuya_api.client_id\r\nmsg.tuya_api.time un timestamp\r\nmsg.tuya_api.device_id\r\nmsg.tuya_api.user_id\r\nmsg.tuya_api.commande commande aiguillant entre ordre de configuration ou relevé de statut de l'entité.\r\nmsg.tuya_api.ordre ordre à passer à l'entité\r\n\r\n","category":"smarthome","in":[{"x":100,"y":220,"wires":[{"id":"cc34878229ba459b"},{"id":"22c9308e64d572f2"}]}],"out":[{"x":1840,"y":620,"wires":[{"id":"eb7d0fb48dfeea11","port":0}]}],"env":[],"meta":{},"color":"#DDAA99"},{"id":"6b3e51e7263bd40c","type":"function","z":"d8d288c742b5c81b","g":"4dfe7d10f3f1a3fb","name":"Connexion1","func":"var url = \"https://openapi.tuyaeu.com/v1.0/token?grant_type=1\";\nvar t = msg.tuya_api.time;\nvar sign = msg.payload;\nvar client_id = msg.tuya_api.client_id;\n\nmsg.headers ={\n \"sign_method\": \"HMAC-SHA256\",\n \"client_id\" : client_id,\n \"t\": t.toString(),\n \"sign\": sign.toUpperCase(),\n },\n \n msg.payload = '';\n msg.url = url;\n msg.method = \"GET\";\n msg.tuya_api.sign_secret = sign;\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":910,"y":220,"wires":[["046627bc0bc11fbb"]]},{"id":"046627bc0bc11fbb","type":"http request","z":"d8d288c742b5c81b","g":"4dfe7d10f3f1a3fb","name":"","method":"use","ret":"obj","paytoqs":"ignore","url":"","tls":"","persist":false,"proxy":"","authType":"","x":1110,"y":220,"wires":[["0ac904677470531b"]]},{"id":"cc34878229ba459b","type":"function","z":"d8d288c742b5c81b","g":"4dfe7d10f3f1a3fb","name":"Create signStr","func":"let client_id = msg.tuya_api.client_id;\nlet t = msg.tuya_api.time;\n\nnode.status({fill:\"red\",shape:\"ring\",text:client_id});\nlet method = \"GET\";\nlet sign_url = \"/v1.0/token?grant_type=1\";\n\n// Couldn't get nodered to process an empty string so this is a hash of an empty file\nlet content_hash = \"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855\";\nlet string_to_sign = method+\"\\n\"+content_hash+\"\\n\"+\"\"+\"\\n\"+sign_url;\nmsg.payload = client_id+t+string_to_sign;\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":480,"y":220,"wires":[["f3818dca4e177f69"]]},{"id":"f3818dca4e177f69","type":"hmac","z":"d8d288c742b5c81b","g":"4dfe7d10f3f1a3fb","name":"Sign signStr with secret","algorithm":"HmacSHA256","key":"58fb24515a07454886120147b4225450","x":690,"y":220,"wires":[["6b3e51e7263bd40c"]]},{"id":"0ac904677470531b","type":"function","z":"d8d288c742b5c81b","g":"4dfe7d10f3f1a3fb","name":"Extract Token from Response","func":"var data = msg.payload;\nvar access = data.result.access_token;\nvar refresh = data.result.refresh_token;\n\n//msg.creds = {};\nmsg.tuya_api.access_token = access\nmsg.tuya_api.refresh_token = refresh;\n\nmsg.payload = msg.tuya_api.ordre;\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":1340,"y":220,"wires":[["f66948c2c5ba3d70"]]},{"id":"f66948c2c5ba3d70","type":"function","z":"d8d288c742b5c81b","name":"Liste des opérations","func":"if (msg.tuya_api.commande == 0){\n return [msg,null];\n} else if (msg.tuya_api.commande == 1){\n return [null,msg];\n}else {\n node.warn(\"La valeur de la commande n'est pas connue\");\n}","outputs":2,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":200,"y":460,"wires":[["0d8eb54a529bf85e","2064e8ad64cd37f6"],["6f079306406b226b","f30fdead3ce3856b"]],"outputLabels":["0","1"]},{"id":"ee971e8557275277","type":"function","z":"d8d288c742b5c81b","g":"cfd6cdedc4113f75","name":"Connexion2","func":"let device_id = msg.tuya_api.device_id;\nlet url = \"https://openapi.tuyaeu.com/v1.0/devices/\" + device_id + \"/commands\";\nlet t = msg.time;\nlet client_id = msg.tuya_api.client_id;\nlet access_token = msg.tuya_api.access_token;\nlet sign = msg.payload;\n\nmsg.headers ={\n \"sign_method\": \"HMAC-SHA256\",\n \"client_id\" : client_id,\n \"t\": t.toString(),\n \"mode\" : \"cors\",\n \"Content-Type\": \"application/json\",\n \"sign\": sign.toUpperCase(),\n \"access_token\" : access_token,\n },\n\nmsg.payload = msg.tuya_api.ordre;\nmsg.url = url;\nmsg.method = \"POST\";\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":1430,"y":420,"wires":[["6222843a323ae47f"]]},{"id":"6222843a323ae47f","type":"http request","z":"d8d288c742b5c81b","g":"cfd6cdedc4113f75","name":"","method":"use","ret":"obj","paytoqs":"ignore","url":"","tls":"","persist":false,"proxy":"","insecureHTTPParser":false,"authType":"","senderr":false,"headers":[],"x":1610,"y":420,"wires":[["9c338d50728a3fc8","c75f94b3825f07bd"]]},{"id":"c730d9c21c85b6c1","type":"function","z":"d8d288c742b5c81b","g":"cfd6cdedc4113f75","name":"Create signStr","func":"//let creds = flow.get(\"tuya\");\nlet access_token = msg.tuya_api.access_token;\nlet device_id = msg.tuya_api.device_id;\nlet t = msg.tuya_api.time;\nlet client_id = msg.tuya_api.client_id;\n\nlet method = \"POST\";\nlet sign_url = \"/v1.0/devices/\" + device_id + \"/commands\";\nlet content_hash = msg.payload;\n\nlet string_to_sign = method+\"\\n\"+content_hash+\"\\n\"+\"\"+\"\\n\"+sign_url;\nlet signStr = client_id + access_token + t + string_to_sign;\n\nmsg.payload = signStr;\n//msg.time = msg.time;\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":940,"y":420,"wires":[["80f2ce055feca5f9"]]},{"id":"80f2ce055feca5f9","type":"hmac","z":"d8d288c742b5c81b","g":"cfd6cdedc4113f75","name":"Sign signStr with secret","algorithm":"HmacSHA256","key":"58fb24515a07454886120147b4225450","x":1190,"y":420,"wires":[["ee971e8557275277"]]},{"id":"0d8eb54a529bf85e","type":"digest","z":"d8d288c742b5c81b","g":"cfd6cdedc4113f75","name":"Hash the body data","algorithm":"SHA256","x":710,"y":420,"wires":[["c730d9c21c85b6c1"]]},{"id":"08e4cb4a36124ade","type":"comment","z":"d8d288c742b5c81b","g":"cfd6cdedc4113f75","name":"Donner un ordre","info":"","x":480,"y":340,"wires":[]},{"id":"bfb85005e1a20a62","type":"comment","z":"d8d288c742b5c81b","g":"4dfe7d10f3f1a3fb","name":"Récupérer un token","info":"","x":490,"y":160,"wires":[]},{"id":"4ad7112320d38417","type":"function","z":"d8d288c742b5c81b","g":"6565106fc2673045","name":"Connexion3","func":"let device_id = msg.tuya_api.device_id;\nlet url = \"https://openapi.tuyaeu.com/v1.0/devices/\" + device_id + \"/status\";\nlet t = msg.tuya_api.time;\nlet method = \"GET\";\nlet client_id = msg.tuya_api.client_id;\n//let creds = flow.get(\"tuya\");\nlet token = msg.tuya_api.access_token;\n//let sign = msg.payload;\nlet sign = msg.payload;\n\nmsg.headers ={\n \"sign_method\": \"HMAC-SHA256\",\n \"client_id\" : client_id,\n \"t\": t.toString(),\n \"mode\" : \"cors\",\n \"Content-Type\": \"application/json\",\n \"sign\": sign.toUpperCase(),\n \"access_token\" : token\n },\n\n msg.payload = '';\n msg.url = url;\n msg.method = \"GET\";\n \nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":970,"y":640,"wires":[["eb7d0fb48dfeea11"]]},{"id":"eb7d0fb48dfeea11","type":"http request","z":"d8d288c742b5c81b","g":"6565106fc2673045","name":"","method":"use","ret":"obj","paytoqs":"ignore","url":"","tls":"","persist":false,"proxy":"","authType":"","x":1170,"y":640,"wires":[[]]},{"id":"174a610c49d94236","type":"comment","z":"d8d288c742b5c81b","g":"6565106fc2673045","name":"Get Status Of Device","info":"","x":500,"y":580,"wires":[]},{"id":"9c338d50728a3fc8","type":"debug","z":"d8d288c742b5c81b","d":true,"name":"debug 309","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":1870,"y":420,"wires":[]},{"id":"6f079306406b226b","type":"function","z":"d8d288c742b5c81b","g":"6565106fc2673045","name":"Create signStr","func":"let access_token = msg.tuya_api.access_token;\nlet device_id = msg.tuya_api.device_id;\nlet t = msg.tuya_api.time;\nlet client_id = msg.tuya_api.client_id;\n\nlet method = \"GET\";\nlet sign_url = \"/v1.0/devices/\" + device_id + \"/status\";\nlet content_hash = \"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855\";\n\nlet string_to_sign = method + \"\\n\" + content_hash + \"\\n\" + \"\" + \"\\n\" + sign_url;\nlet signStr = client_id + access_token + t + string_to_sign;\n\nmsg.payload = signStr;\n//msg.time = msg.tuya_api.time;\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":480,"y":640,"wires":[["b7dac392bb492edb"]]},{"id":"b7dac392bb492edb","type":"hmac","z":"d8d288c742b5c81b","g":"6565106fc2673045","name":"Sign signStr with secret","algorithm":"HmacSHA256","key":"58fb24515a07454886120147b4225450","x":710,"y":640,"wires":[["4ad7112320d38417"]]},{"id":"22c9308e64d572f2","type":"debug","z":"d8d288c742b5c81b","d":true,"g":"4dfe7d10f3f1a3fb","name":"debug 336","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":390,"y":80,"wires":[]},{"id":"2064e8ad64cd37f6","type":"debug","z":"d8d288c742b5c81b","d":true,"name":"debug 337","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":310,"y":340,"wires":[]},{"id":"f30fdead3ce3856b","type":"debug","z":"d8d288c742b5c81b","d":true,"name":"debug 338","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":250,"y":620,"wires":[]},{"id":"c75f94b3825f07bd","type":"delay","z":"d8d288c742b5c81b","name":"","pauseType":"delay","timeout":"2","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"allowrate":false,"outputs":1,"x":1260,"y":500,"wires":[["6f079306406b226b"]]},{"id":"cfd6cdedc4113f75","type":"group","z":"d8d288c742b5c81b","style":{"stroke":"#999999","stroke-opacity":"1","fill":"none","fill-opacity":"1","label":true,"label-position":"nw","color":"#a4a4a4"},"nodes":["ee971e8557275277","6222843a323ae47f","c730d9c21c85b6c1","80f2ce055feca5f9","0d8eb54a529bf85e","08e4cb4a36124ade"],"x":374,"y":299},{"id":"4dfe7d10f3f1a3fb","type":"group","z":"d8d288c742b5c81b","style":{"stroke":"#999999","stroke-opacity":"1","fill":"none","fill-opacity":"1","label":true,"label-position":"nw","color":"#a4a4a4"},"nodes":["6b3e51e7263bd40c","046627bc0bc11fbb","cc34878229ba459b","f3818dca4e177f69","0ac904677470531b","bfb85005e1a20a62","22c9308e64d572f2"],"x":294,"y":39},{"id":"6565106fc2673045","type":"group","z":"d8d288c742b5c81b","style":{"stroke":"#999999","stroke-opacity":"1","fill":"none","fill-opacity":"1","label":true,"label-position":"nw","color":"#a4a4a4"},"nodes":["4ad7112320d38417","eb7d0fb48dfeea11","174a610c49d94236","6f079306406b226b","b7dac392bb492edb"],"x":374,"y":539},{"id":"ef69c7a52302b57c","type":"function","z":"575207865d1e30df","name":"Valeurs Entites","func":"var message = msg.entity_var;\n\nif (typeof (flow.get(msg.id)) === \"undefined\") {\n flow.set(msg.id, {});\n}\n\nvar Pos = flow.get(msg.id);\nPos.tuya_api = {};\nlet Tuya = Pos.tuya_api;\nTuya.client_id = flow.get(\"tuya_client_id\");\nTuya.user_id = flow.get(\"tuya_user_id\");\nTuya.device_id = msg.device_id;\nTuya.time = msg.time;\n\nPos.action = msg.action;\n\nif (msg.action != 7){\n msg.test = {};\n let Id = flow.get(msg.id);\n let valeur = {};\n if (typeof (Id.positionnement) === \"undefined\") {\n valeur.positionnement = {};\n valeur.positionnement.pourcentage = null;\n valeur.positionnement.new_position = null;\n valeur.positionnement.new_azimut = Number(msg.azimut);\n flow.set(msg.id, valeur);\n }\n Id.positionnement.new_azimut = Number(msg.azimut);\n Tuya.commande = 0;\n\n //Pos.entity_var = {};\n let sortie = Pos.entity_var;\n let message_length = message.length;\n for (var i = 0; i < message_length; i++) {\n if (message[i][\"entity_id\"].match(/volet['_'[a-z]]*/i)){\n if (message[i][\"entity_id\"].match(/auto_offset_ouvre/i)){\n //sortie['offset_ouv'] = Number(message[i][\"state\"]);\n msg.offset_ouv = Number(message[i][\"state\"]);\n } else if (message[i][\"entity_id\"].match(/auto_offset_ferme/i)) {\n //sortie['offset_ferm'] = Number(message[i][\"state\"]);\n msg.offset_ferm = Number(message[i][\"state\"]);\n } else if (message[i][\"entity_id\"].match(/volets_auto_matin_toggle/i)) {\n msg.toggle_m = message[i][\"state\"];\n } else if (message[i][\"entity_id\"].match(/volets_auto_soir_toggle/i)) {\n msg.toggle_s = message[i][\"state\"];\n } else if (message[i][\"entity_id\"].match(/volets_auto_time_ouvre/i)) {\n msg.time_m = message[i][\"state\"];\n } else if (message[i][\"entity_id\"].match(/volets_auto_time_ferme/i)) {\n msg.time_s = message[i][\"state\"];\n }\n }\n }\n} else {\n Tuya.commande = 1;\n}\n\n//msg.entity_var = {};\nreturn msg;\n","outputs":1,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":1420,"y":360,"wires":[["a3cb30b1067bedd2","55c81f3ed234fc1d"]],"info":"Récupére les valeurs du tableau de bord liées à msg.id (une pièce)\r\n\r\nStructure les valeurs devant persister en mémoire."},{"id":"bcf894fa9b000b17","type":"ha-get-entities","z":"575207865d1e30df","name":"Liste entitées","server":"8ba7aec4.1022e","version":0,"rules":[{"property":"entity_id","logic":"jsonata","value":"$contains(\t $entity().entity_id,\t id\t)","valueType":"jsonata"}],"output_type":"array","output_empty_results":true,"output_location_type":"msg","output_location":"entity_var","output_results_count":1,"x":1210,"y":360,"wires":[["ef69c7a52302b57c"]]},{"id":"9b44297846ea637e","type":"function","z":"575207865d1e30df","name":"Action volet","func":"let Obj = flow.get(msg.id);\n\nif (Obj.action != 3 && Obj.action != 7) {\n\n// On vérifie que le volet ne soit pas déjà dans la bonne position\n if (Obj.positionnement.pourcentage != Obj.positionnement.new_position) {\n Obj.tuya_api.ordre = \"{ \\\"commands\\\": [{ \\\"code\\\" : \\\"percent_control\\\", \\\"value\\\" : \" + Obj.positionnement.pourcentage + \"}]}\";\n //On bascule à 1 la variable \"act_ha\" pour dire au programme que l'action a été demandée par HA\n\n Obj.act_ha = 1;\n node.status({ fill: \"green\", text: \"Pourcent: \" + Obj.positionnement.pourcentage });\n msg.tuya_api = Obj.tuya_api;\n return msg;\n }\n\n node.status({ fill: \"green\", text: \"Dif: \" + Obj.action});\n\n} else if (Obj.action == 3) {\n Obj.tuya_api.ordre = \"{ \\\"commands\\\" : [{ \\\"code\\\" : \\\"control\\\", \\\"value\\\" : \\\"stop\\\"}]}\";\n // On bascule à 1 la variable \"act_ha\" pour dire au programme que l'action a été demandée par HA\n\n Obj.act_ha = 1;\n node.status({ fill: \"red\", text: \"stop\"});\n msg.tuya_api = Obj.tuya_api;\n return msg;\n\n} else if (Obj.action == 7){\n\n // On simule l'action hors HA en rafraichissant les valeurs depuis le cloud\n Obj.act_ha = 0\n msg.tuya_api = Obj.tuya_api;\n node.status({ fill: \"yellow\", text: \"Refesh\" });\n return msg;\n\n} else {\n node.status({ fill: \"yellow\", text: \"Aucune action\" });\n}","outputs":1,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":2110,"y":340,"wires":[["c3ed1aa18958467a","9ed04df207b5aaa8"]],"info":"Modifie le payload afin de fournir au sous programme les bonnes informations à exécuter"},{"id":"3c9afc49bd7a370e","type":"function","z":"575207865d1e30df","name":"Global Settings CLICK On Start TAB","func":"\nreturn msg;","outputs":1,"noerr":0,"initialize":"var client_id = \"Le Votre\";\nvar user_id = \"Le Votre\";\nflow.set(\"tuya_client_id\", client_id);\nflow.set(\"tuya_user_id\", user_id );\n\n","finalize":"","libs":[],"x":170,"y":40,"wires":[[]],"info":"L'objectif de cette fonction est de fournir les variables de connexion aux APIs\r\n\r\nLa récupération des valeurs est décrite [ici](https://forum.hacf.fr/t/api-tuya-depuis-node-red/28774/11)\r\n\r\nLes valeurs récupérées sont à saisir dans l'onglet \"On Start\"\r\n\r\n    client_id\r\n\r\n    user_id"},{"id":"488bbea2e3756767","type":"server-state-changed","z":"575207865d1e30df","name":"Elevation","server":"8ba7aec4.1022e","version":5,"outputs":1,"exposeAsEntityConfig":"","entityId":"sensor.sunelevation","entityIdType":"exact","outputInitially":false,"stateType":"str","ifState":"","ifStateType":"str","ifStateOperator":"is","outputOnlyOnStateChange":true,"for":"0","forType":"num","forUnits":"minutes","ignorePrevStateNull":false,"ignorePrevStateUnknown":false,"ignorePrevStateUnavailable":false,"ignoreCurrentStateUnknown":false,"ignoreCurrentStateUnavailable":false,"outputProperties":[{"property":"payload","propertyType":"msg","value":"","valueType":"entityState"}],"x":80,"y":80,"wires":[["b227b178e36761eb"]],"info":"Récupére le niveau d'élévation du soleil\r\n\r\nNecessite l'intégration \"sun\" de Home Assistant"},{"id":"b227b178e36761eb","type":"function","z":"575207865d1e30df","name":"Taux Ouverture","func":"var niveau;\n\nif (msg.payload > 20 && msg.payload <= 60) {\n niveau = 80;\n} else if (msg.payload > 60) {\n niveau = 65;\n} else {\n niveau = 100;\n}\nnode.status({ fill: \"green\", text: niveau });\nmsg.payload = niveau;\nreturn msg;\n","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":340,"y":80,"wires":[["b04f243b43f60dbd"]],"info":"Objectif\r\n\r\nFournir un taux d'élévation du volet en fonction du niveau d'élavation du soleil (msg.payload).\r\n\r\nCette donnée est utilisé par la suite par la fonction azimut\r\n\r\nDans une futur version elle sera potentiellement affectée directement à chaque volet"},{"id":"b04f243b43f60dbd","type":"change","z":"575207865d1e30df","name":"elevation","rules":[{"t":"set","p":"elevation","pt":"flow","to":"payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":560,"y":80,"wires":[[]],"info":"Instancie la variable flow.elevation"},{"id":"faf2848fb11e84f3","type":"server-state-changed","z":"575207865d1e30df","name":"azimut","server":"8ba7aec4.1022e","version":5,"outputs":1,"exposeAsEntityConfig":"","entityId":"sensor.sunazimuth","entityIdType":"exact","outputInitially":false,"stateType":"num","ifState":"","ifStateType":"str","ifStateOperator":"is","outputOnlyOnStateChange":true,"for":"0","forType":"num","forUnits":"minutes","ignorePrevStateNull":false,"ignorePrevStateUnknown":false,"ignorePrevStateUnavailable":false,"ignoreCurrentStateUnknown":false,"ignoreCurrentStateUnavailable":false,"outputProperties":[{"property":"action","propertyType":"msg","value":"2","valueType":"num"},{"property":"azimut","propertyType":"msg","value":"","valueType":"entityState"}],"x":70,"y":200,"wires":[["6d7265beda5e72f6"]],"info":"Récupére l'azimut du soleil\r\n\r\nNecessite l'intégration \"sun\" de Home Assistant"},{"id":"a3cb30b1067bedd2","type":"function","z":"575207865d1e30df","name":"Positionnement","func":"var Obj = flow.get(msg.id)\n\nif (Obj.action == 0) {\n // Gestion de l'onverture\n Obj.positionnement.pourcentage = 100;\n return [msg, null, null];\n\n} else if (Obj.action == 1) {\n // Gestion de la fermeture\n Obj.positionnement.pourcentage = 0;\n return [msg, null, null];\n\n} else if (Obj.action == 2){\n \n // Gestion de l'azimut\n let azimut = Obj.positionnement.new_azimut;\n let actual_position = Obj.positionnement.new_position;\n let goal_position = Number(flow.get('elevation'));\n\n if (Obj.entity_var.auto_azimut == \"on\") {\n if ((azimut > msg.azi_min && azimut < msg.azi_max) && flow.get('meteo') == \"Ensoleillé\" ) {\n if (actual_position != goal_position) {\n // Le mouvement du volet va s'opérer en fonction de la variable pourcentage\n \n Obj.positionnement.pourcentage = goal_position;\n node.status({ fill: \"green\", text: \"Niveau: \" + goal_position });\n return [msg, null, null];\n }\n \n } else if (actual_position != 100) {\n //Si l'on est hors plage d'azimut, on rouvre le volet totalement si la fonction azimut est activée\n\n Obj.positionnement.pourcentage = 100;\n node.status({ fill: \"blue\", text: \"Niveau: 100\" });\n return [msg, null, null];\n \n } else {\n // Si on est hors plage d'azimut et que le volet est déjà ouvert\n node.status({ fill: \"yellow\", text: \"Aucune action\" });\n }\n }\n} else if (Obj.action == 3){\n //Gestion de l'arrêt. L'ordre est géré plus loin\n return [msg, null, null];\n\n} else if (Obj.action == 4) {\n // Gestion du taux d'ouverture\n node.status({ fill: \"green\", text: \"Action 4\" });\n Obj.positionnement.pourcentage = Number(msg.taux);\n return [msg, null, null];\n\n} else if (Obj.action == 5) {\n //Gestion de l'ouverture le matin\n node.status({ fill: \"green\", text: \"Action 5\"});\n //Bifurque afin de vérifier l'heure du matin\n if (msg.toggle_m == \"on\") {\n Obj.positionnement.pourcentage = 100;\n return [null, msg, null];\n } else {\n //conversion de l'heure fourni en timestamp\n let heure = msg.time_m;\n let temp = heure.split(\":\");\n let timestampheure = ((parseInt(temp[0]) * 60) + parseInt(temp[1])) * 60 + parseInt(temp[2]);\n\n // Récupération du timestamp courant\n temp = new Date();\n heure = temp.getHours();\n let minute = temp.getMinutes();\n let seconde = temp.getSeconds();\n let timestampcurrent = ((heure * 60) + minute) * 60 + seconde;\n if (timestampheure >= (timestampcurrent - 120) && timestampheure <= (timestampcurrent + 120)){\n Obj.positionnement.pourcentage = 100;\n return [msg, null, null];\n } else\n node.status({ fill: \"yellow\", text: \"Action 5: Aucune action\" });\n }\n\n} else if (Obj.action == 6) {\n //Gestion de la fermeture le soir\n node.status({ fill: \"green\", text: \"Action 6\" });\n //Bifurque afin de vérifier l'heure du soir\n if (msg.toggle_s == \"on\") {\n Obj.positionnement.pourcentage = 0;\n return [null, null, msg];\n } else {\n //conversion de l'heure fourni en timestamp\n let heure = msg.time_s;\n let temp = heure.split(\":\");\n let timestampheure = ((parseInt(temp[0]) * 60) + parseInt(temp[1])) * 60 + parseInt(temp[2]);\n\n // Récupération du timestamp courant\n temp = new Date();\n heure = temp.getHours();\n let minute = temp.getMinutes();\n let seconde = temp.getSeconds();\n let timestampcurrent = ((heure * 60) + minute) * 60 + seconde;\n if (timestampheure >= (timestampcurrent - 120) && timestampheure <= (timestampcurrent + 120)) {\n Obj.positionnement.pourcentage = 0;\n return [msg, null, null];\n } else\n node.status({ fill: \"yellow\", text: \"Action 5: Aucune action\" });\n } \n\n} else if (Obj.action == 7) {\n return [msg, null, null];\n}","outputs":3,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":1660,"y":360,"wires":[["9b44297846ea637e","1b134a1d6e225401"],["d9afd42e8a5f2e7c"],["9270ef84952505bf"]],"outputLabels":["Manuelle","Offset_matin","Offset_soir"],"info":"En fonction du programme utilisé, affecte la valeur souhaitée à la variable:\r\n\r\npositionnement.pourcentage"},{"id":"4f2f91e4f7cb5039","type":"server-state-changed","z":"575207865d1e30df","name":"meteo","server":"8ba7aec4.1022e","version":5,"outputs":1,"exposeAsEntityConfig":"","entityId":"sensor.lavaur_daily_original_condition","entityIdType":"exact","outputInitially":false,"stateType":"str","ifState":"","ifStateType":"str","ifStateOperator":"is","outputOnlyOnStateChange":true,"for":"0","forType":"num","forUnits":"minutes","ignorePrevStateNull":false,"ignorePrevStateUnknown":false,"ignorePrevStateUnavailable":false,"ignoreCurrentStateUnknown":false,"ignoreCurrentStateUnavailable":false,"outputProperties":[{"property":"payload","propertyType":"msg","value":"","valueType":"entityState"},{"property":"bouton","propertyType":"msg","value":"","valueType":"triggerId"}],"x":70,"y":140,"wires":[["59e4e624b1be226d"]],"info":"Récupére la météo du jour grace à l'intégration: \"Météo France\""},{"id":"59e4e624b1be226d","type":"change","z":"575207865d1e30df","name":"meteo","rules":[{"t":"set","p":"meteo","pt":"flow","to":"payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":550,"y":140,"wires":[[]],"info":"Instancie la variable flow.meteo"},{"id":"313b49b06ac1e4af","type":"function","z":"575207865d1e30df","name":"MàJ Pourcentage","func":"let message = msg.payload.result;\nlet message_length = message.length;\nlet Obj = flow.get(msg.id);\nlet Pos = Obj.positionnement;\n\nfor (var i = 0; i < message_length; i++) {\n if (message[i][\"code\"].match(/percent_control/i)){\n var new_value = message[i][\"value\"]\n }\n}\n\n/* Si la nouvelle position détectée ne correspond pas à celle du progamme\non la met à jour et on poursuit sinon on s'arrête*/\nif (Pos.new_position != new_value) {\n Pos.new_position = new_value;\n return msg;\n}\n\n","outputs":1,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":1530,"y":660,"wires":[["cbba7c7b1aa9746a","c14c62966e0fdac3","396c628523c91b01","1b7af5409c93858b","8a27ce7a9c763e14"]],"info":"Récupére la valeur d'ouverture en sortie de subflow afin de la comparer à la valeur stockée.\r\n\r\nCette fonction permet de mettre à jour la position du volet suite à une action manuelle sur l'interrupteur."},{"id":"4806e36ad01b37b4","type":"link out","z":"575207865d1e30df","name":"link out 76","mode":"link","links":["f16a017b0ec4ef0b","1f499c036878ca3e","76f4f86875a83812","3cc1417c9c0eab01","9137ca172d8be8f0","2b2892f6615c9809","27972266d1eca80b"],"x":555,"y":200,"wires":[]},{"id":"e5524eec8adfea50","type":"link in","z":"575207865d1e30df","name":"link in 60","links":["3435c1ac287473d5","431c7f2132e0d0f9","bd66fda3ba2151fd","30a7d41c6c5944f5","d4cfba64cb3b75b7","fde8f0f2e7758b9c","2d630bf2cd0534a2"],"x":1095,"y":360,"wires":[["bcf894fa9b000b17"]]},{"id":"6d7265beda5e72f6","type":"api-current-state","z":"575207865d1e30df","name":"Azimut auto global","server":"8ba7aec4.1022e","version":3,"outputs":2,"halt_if":"on","halt_if_type":"str","halt_if_compare":"is","entity_id":"input_boolean.volets_auto_azimut_global","state_type":"str","blockInputOverrides":false,"outputProperties":[],"for":"0","forType":"num","forUnits":"minutes","override_topic":false,"state_location":"payload","override_payload":"msg","entity_location":"data","override_data":"msg","x":330,"y":200,"wires":[["4806e36ad01b37b4"],[]],"info":"Récupére le commutateur input_boolean.volets_auto_azimut_global\r\n\r\nSi ce dernier est activé, donc à \"on\" ou **noir** dans l'interface, on continue le programme\r\n\r\nSi ce dernier est désactivé, donc à \"off\" ou **rouge** dans l'interface, on arrête le programme"},{"id":"d9afd42e8a5f2e7c","type":"within-time-switch","z":"575207865d1e30df","name":"Plage matin","nameInt":"","positionConfig":"403a6e4bd797cb6e","startTime":"sunriseStart","startTimeType":"pdsTime","startOffset":"offset_ouv","startOffsetType":"msg","startOffsetMultiplier":60000,"endTime":"sunriseEnd","endTimeType":"pdsTime","endOffset":"offset_ouv","endOffsetType":"msg","endOffsetMultiplier":60000,"timeRestrictions":0,"timeRestrictionsType":"none","timeDays":"*","timeOnlyOddDays":false,"timeOnlyEvenDays":false,"timeOnlyOddWeeks":false,"timeOnlyEvenWeeks":false,"timeMonths":"*","timedatestart":"","timedateend":"","propertyStart":"","propertyStartType":"none","propertyStartCompare":"true","propertyStartThreshold":"","propertyStartThresholdType":"num","startTimeAlt":"","startTimeAltType":"entered","startOffsetAlt":0,"startOffsetAltType":"none","startOffsetAltMultiplier":60000,"propertyEnd":"","propertyEndType":"none","propertyEndCompare":"true","propertyEndThreshold":"","propertyEndThresholdType":"num","endTimeAlt":"","endTimeAltType":"entered","endOffsetAlt":0,"endOffsetAltType":"none","endOffsetAltMultiplier":60000,"withinTimeValue":"","withinTimeValueType":"msgInput","outOfTimeValue":"false","outOfTimeValueType":"msgInput","tsCompare":"0","x":1870,"y":380,"wires":[["9b44297846ea637e"],[]]},{"id":"9270ef84952505bf","type":"within-time-switch","z":"575207865d1e30df","name":"Plage soir","nameInt":"","positionConfig":"403a6e4bd797cb6e","startTime":"sunsetStart","startTimeType":"pdsTime","startOffset":"offset_ferm","startOffsetType":"msg","startOffsetMultiplier":60000,"endTime":"sunsetEnd","endTimeType":"pdsTime","endOffset":"offset_ferm","endOffsetType":"msg","endOffsetMultiplier":60000,"timeRestrictions":0,"timeRestrictionsType":"none","timeDays":"*","timeOnlyOddDays":false,"timeOnlyEvenDays":false,"timeOnlyOddWeeks":false,"timeOnlyEvenWeeks":false,"timeMonths":"*","timedatestart":"","timedateend":"","propertyStart":"","propertyStartType":"none","propertyStartCompare":"true","propertyStartThreshold":"","propertyStartThresholdType":"num","startTimeAlt":"","startTimeAltType":"entered","startOffsetAlt":0,"startOffsetAltType":"none","startOffsetAltMultiplier":60000,"propertyEnd":"","propertyEndType":"none","propertyEndCompare":"true","propertyEndThreshold":"","propertyEndThresholdType":"num","endTimeAlt":"","endTimeAltType":"entered","endOffsetAlt":0,"endOffsetAltType":"none","endOffsetAltMultiplier":60000,"withinTimeValue":"","withinTimeValueType":"msgInput","outOfTimeValue":"false","outOfTimeValueType":"msgInput","tsCompare":"0","x":1860,"y":440,"wires":[["9b44297846ea637e"],[]]},{"id":"27ba68ad4922f686","type":"debug","z":"575207865d1e30df","name":"debug 339","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":1530,"y":600,"wires":[]},{"id":"1b134a1d6e225401","type":"debug","z":"575207865d1e30df","name":"debug 340","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":1870,"y":240,"wires":[]},{"id":"c3ed1aa18958467a","type":"debug","z":"575207865d1e30df","name":"debug 341","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":2290,"y":240,"wires":[]},{"id":"55c81f3ed234fc1d","type":"debug","z":"575207865d1e30df","name":"debug 342","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":1630,"y":240,"wires":[]},{"id":"9ed04df207b5aaa8","type":"link out","z":"575207865d1e30df","name":"link out 87","mode":"link","links":["4a0fc73bdbded94d"],"x":2325,"y":340,"wires":[]},{"id":"4a0fc73bdbded94d","type":"link in","z":"575207865d1e30df","name":"link in 68","links":["9ed04df207b5aaa8"],"x":1105,"y":660,"wires":[["a30910a7616af66a"]]},{"id":"ef8678a601244c43","type":"debug","z":"575207865d1e30df","name":"debug 349","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":930,"y":220,"wires":[]},{"id":"8a27ce7a9c763e14","type":"debug","z":"575207865d1e30df","name":"debug 350","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":1770,"y":860,"wires":[]},{"id":"a30910a7616af66a","type":"subflow:d8d288c742b5c81b","z":"575207865d1e30df","name":"","x":1290,"y":660,"wires":[["313b49b06ac1e4af","27ba68ad4922f686"]]},{"id":"10ef606d1ddfc682","type":"group","z":"575207865d1e30df","name":"","style":{"fill":"#ffffbf","fill-opacity":"0.72","label":true},"nodes":["1b7af5409c93858b","c14c62966e0fdac3","396c628523c91b01","92c53ced5c6ddbb4","cbba7c7b1aa9746a","d36b022c2220db5c","1fe263b910724190"],"x":1754,"y":539,"w":712,"h":262},{"id":"1b7af5409c93858b","type":"function","z":"575207865d1e30df","g":"10ef606d1ddfc682","name":"Texte_Log","func":"let Obj = flow.get(msg.id);\nvar elevation = Obj.positionnement.pourcentage;\n\nnode.status({ fill: \"green\", text: Obj.act_ha });\n\nif ( Obj.act_ha == 1 ){\n if ( Obj.action == 0 ){\n msg.bouton = \"Ouverture\";\n msg.etat = \"Enclenché\";\n msg.message = \"Action HA\"\n } else if (Obj.action == 1) {\n msg.bouton = \"Fermeture\";\n msg.etat = \"Enclenché\";\n msg.message = \"Action HA\"\n } else if (Obj.action == 2) {\n msg.bouton = \"Azimut\";\n msg.etat = \"Enclenché\";\n msg.message = \"Action HA\"\n } else if (Obj.action == 3) {\n msg.bouton = \"Stop\";\n msg.etat = \"Enclenché\";\n msg.message = \"Action HA\"\n } else if (Obj.action == 4) {\n msg.bouton = \"Taux d'ouverture\";\n msg.etat = \"Enclenché\";\n msg.message = \"Action HA\"\n } else if (Obj.action == 5) {\n msg.bouton = \"Ouverture auto\";\n msg.etat = \"Enclenché\";\n msg.message = \"Action HA\"\n } else if (Obj.action == 6) {\n msg.bouton = \"Fermeture auto\";\n msg.etat = \"Enclenché\";\n msg.message = \"Action HA\"\n }\n}else if (Obj.act_ha == 0) {\n msg.bouton = \"Boutons physiques\";\n msg.etat = \"Enclenché\";\n msg.message = \"Action hors HA\"\n}\n\nreturn msg;","outputs":1,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":1850,"y":760,"wires":[["1fe263b910724190"]],"info":"Fonction gérant le log des actions demandées au volet"},{"id":"c14c62966e0fdac3","type":"function","z":"575207865d1e30df","g":"10ef606d1ddfc682","name":"Changement affichage Niveau","func":"let Obj = flow.get(msg.id);\nlet Pos = Obj.positionnement;\n\n//context.flow.set(\"pourcentage\", msg.payload, \"default\");\nlet entite = \"input_number.volets_niveau_\" + msg.id;\nmsg.payload = {\n domain: \"input_number\",\n service: \"set_value\",\n target: {\n \"entity_id\": [entite]\n },\n data: {\n \"value\": Pos.new_position\n }\n}\n\nreturn msg;","outputs":1,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":1910,"y":640,"wires":[["92c53ced5c6ddbb4"]],"info":"MAJ de la valeur pourcentage du tableau de bord non mise à jour en cas de déclenchement manuel\r\nIl est considéré que les actions par défaut sont réalisées par boutons physiques donc hors HA"},{"id":"396c628523c91b01","type":"function","z":"575207865d1e30df","g":"10ef606d1ddfc682","name":"Changement Etat Bouton","func":"let Obj = flow.get(msg.id)\n\nif (Obj.action == 0) {\n let entite = \"input_boolean.volets_up_\" + msg.id;\n msg.payload = {\n \"domain\": \"input_boolean\",\n \"service\": \"turn_off\",\n \"target\": {\n \"entity_id\": [entite]\n }\n }\n node.status({ fill: \"blue\", text: \"Bascule up\" });\n return msg;\n} else if (Obj.action == 1) {\n let entite = \"input_boolean.volets_down_\" + msg.id;\n msg.payload = {\n \"domain\": \"input_boolean\",\n \"service\": \"turn_off\",\n \"target\": {\n \"entity_id\": [entite]\n }\n }\n node.status({ fill: \"blue\", text: \"Bascule down\" });\n return msg;\n} else if (Obj.action == 3 ) {\n let entite = \"input_boolean.volets_stop_\" + msg.id;\n msg.payload = {\n domain: \"input_boolean\",\n service: \"turn_off\",\n target: {\n entity_id: [entite]\n }\n }\n node.status({ fill: \"blue\", text: \"stop\"});\n return msg;\n}\n","outputs":1,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":1890,"y":700,"wires":[["92c53ced5c6ddbb4"]],"info":"Fonction permettant de rebasculer les boutons au statut off après leur activation"},{"id":"92c53ced5c6ddbb4","type":"api-call-service","z":"575207865d1e30df","g":"10ef606d1ddfc682","name":"","server":"8ba7aec4.1022e","version":5,"debugenabled":false,"domain":"","service":"","areaId":[],"deviceId":[],"entityId":[],"data":"","dataType":"jsonata","mergeContext":"","mustacheAltTags":false,"outputProperties":[],"queue":"none","x":2210,"y":640,"wires":[["d36b022c2220db5c"]]},{"id":"cbba7c7b1aa9746a","type":"function","z":"575207865d1e30df","g":"10ef606d1ddfc682","name":"Changement azimut Bouton","func":"//var message = msg.payload;\nlet Obj = flow.get(msg.id);\n\n/* Si le volet s'ouvre à 100%, la fonction azimut est automatiquement basculée à activé*/\nif (Obj.new_position == 100 ) {\n let entite = \"input_boolean.volets_auto_azimut_\" + msg.id;\n msg.payload = {\n domain: \"input_boolean\",\n service: \"turn_on\",\n target: {\n entity_id: [entite]\n }\n }\n node.status({ fill: \"green\", text: Obj.new_position });\n return msg;\n\n/*Si le volet n'est pas ouvert totalement et qu'on n'est pas sur une action automatique,\n la fonction azimut est désactivée. C'est le cas ou on ouvre puis on décide d'appuyer sur le bouton\n pour refermer partiellement le volet*/\n} else if (Obj.new_position != 100 && Number(Obj.action) != 2){\n let entite = \"input_boolean.volets_auto_azimut_\" + msg.id;\n msg.payload = {\n domain: \"input_boolean\",\n service: \"turn_off\",\n target: {\n entity_id: [entite]\n }\n }\n node.status({ fill: \"red\", text: Obj.new_position });\n return msg;\n} else {\n node.status({ fill: \"yellow\", text: \"Aucune action\" });\n}","outputs":1,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":1900,"y":580,"wires":[["92c53ced5c6ddbb4"]],"info":"Gére l'activation ou non de la fonction d'ouverture en fonction de l'azimut.\r\n\r\nActive la fonction azimut du volet lors de l'ouverture total de ce dernier. (valeur à 0)\r\n\r\nSi le volet n'est ouvert que partiellement, la fonction ne s'active pas."},{"id":"d36b022c2220db5c","type":"function","z":"575207865d1e30df","g":"10ef606d1ddfc682","name":"Réinit","func":"/*Réinitialisation de la variable \"act_ha\" à 0 pour les actions futures*/\nlet Obj = flow.get(msg.id);\nObj.act_ha = 0;","outputs":1,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":2390,"y":640,"wires":[[]],"info":"Réinitialise la valeur de la variable act_ha"},{"id":"1fe263b910724190","type":"link out","z":"575207865d1e30df","g":"10ef606d1ddfc682","name":"link out 75","mode":"link","links":["48825624e6296d2c"],"x":2225,"y":760,"wires":[]},{"id":"938e591897d41c86","type":"group","z":"575207865d1e30df","name":"Log","style":{"fill":"#bfc7d7","label":true},"nodes":["189e9256ad86a588","efd7bd80b868a635","48825624e6296d2c"],"x":1874,"y":839,"w":552,"h":82},{"id":"189e9256ad86a588","type":"file","z":"575207865d1e30df","g":"938e591897d41c86","name":"log","filename":"filename","filenameType":"msg","appendNewline":true,"createDir":true,"overwriteFile":"false","encoding":"none","x":2350,"y":880,"wires":[[]],"info":"Le log et écrit dans un fichier mensuel dans /config/logs/\"Id\""},{"id":"efd7bd80b868a635","type":"function","z":"575207865d1e30df","g":"938e591897d41c86","name":"Horodatage de la ligne de log","func":"let Obj = flow.get(msg.id);\nlet message = msg.message + \" \" + msg.bouton + \": \" + msg.etat + \"; Niveau: \" + Obj.positionnement.new_position;\n\nconst temp = new Date();\nlet annee = (temp.getFullYear().toString());\nlet mois = (temp.getMonth() + 1).toString().padStart(2, \"0\");\nlet jour = (temp.getDate().toString().padStart(2, \"0\"));\nlet heure = (temp.getHours().toString().padStart(2, \"0\"));\nlet minute = (temp.getMinutes().toString().padStart(2, \"0\"));\nlet seconde = (temp.getSeconds().toString().padStart(2, \"0\"));\n\nlet datetemp = annee + \"-\" + mois;\nmsg.filename = \"/config/logs/\" + datetemp + \"_\" + msg.id + \".log\";\n\n\nlet horodatage = annee + \"-\" + mois + \"-\" + jour + \"_\" + heure + \":\" + minute + \":\" + seconde;\nnode.status({ fill: \"blue\", text: horodatage });\n\nmsg.payload = horodatage + \" \"+ message;\nreturn msg;","outputs":1,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":2100,"y":880,"wires":[["189e9256ad86a588"]]},{"id":"48825624e6296d2c","type":"link in","z":"575207865d1e30df","g":"938e591897d41c86","name":"link in 62","links":["1fe263b910724190"],"x":1915,"y":880,"wires":[["efd7bd80b868a635"]]},{"id":"cf0c264bd8d76173","type":"group","z":"575207865d1e30df","name":"Bureau","style":{"label":true},"nodes":["752a5de99c6ff80d","5987584cd85ac344","58b9fa0fb36ccf93","2944f56e19118bea","5d0d3ef7668a4ccc","ed4b55973ab44531","774b0f631c34df85","f16a017b0ec4ef0b","3435c1ac287473d5","5574b4a7301e429b","4ed1092604d4f241","1dca3aa3afcef4d4","838abe6fd5394eba"],"x":14,"y":259,"w":922,"h":482},{"id":"752a5de99c6ff80d","type":"server-state-changed","z":"575207865d1e30df","g":"cf0c264bd8d76173","name":"Fermeture volet","server":"8ba7aec4.1022e","version":5,"outputs":2,"exposeAsEntityConfig":"","entityId":"input_boolean.volets_down_bureau","entityIdType":"exact","outputInitially":false,"stateType":"str","ifState":"on","ifStateType":"str","ifStateOperator":"is","outputOnlyOnStateChange":true,"for":"0","forType":"num","forUnits":"minutes","ignorePrevStateNull":false,"ignorePrevStateUnknown":false,"ignorePrevStateUnavailable":false,"ignoreCurrentStateUnknown":false,"ignoreCurrentStateUnavailable":false,"outputProperties":[{"property":"action","propertyType":"msg","value":"1","valueType":"num"}],"x":120,"y":400,"wires":[["2944f56e19118bea"],[]],"info":"Récupére le statut du bouton de fermeture du volet\r\n\r\nEntité:\r\n\r\ninput_boolean.volets_down_bureau"},{"id":"5987584cd85ac344","type":"server-state-changed","z":"575207865d1e30df","g":"cf0c264bd8d76173","name":"Ouverture volet","server":"8ba7aec4.1022e","version":5,"outputs":2,"exposeAsEntityConfig":"","entityId":"input_boolean.volets_up_bureau","entityIdType":"exact","outputInitially":false,"stateType":"str","ifState":"on","ifStateType":"str","ifStateOperator":"is","outputOnlyOnStateChange":true,"for":"0","forType":"num","forUnits":"minutes","ignorePrevStateNull":false,"ignorePrevStateUnknown":false,"ignorePrevStateUnavailable":false,"ignoreCurrentStateUnknown":false,"ignoreCurrentStateUnavailable":false,"outputProperties":[{"property":"action","propertyType":"msg","value":"0","valueType":"num"}],"x":120,"y":340,"wires":[["2944f56e19118bea"],[]],"info":"Récupére le statut du bouton d'ouverture du volet\r\n\r\nEntité:\r\n\r\ninput_boolean.volets_up_bureau"},{"id":"58b9fa0fb36ccf93","type":"server-state-changed","z":"575207865d1e30df","g":"cf0c264bd8d76173","name":"Arrêt ouverture","server":"8ba7aec4.1022e","version":5,"outputs":2,"exposeAsEntityConfig":"","entityId":"input_boolean.volets_stop_bureau","entityIdType":"exact","outputInitially":false,"stateType":"str","ifState":"on","ifStateType":"str","ifStateOperator":"is","outputOnlyOnStateChange":true,"for":"0","forType":"num","forUnits":"minutes","ignorePrevStateNull":false,"ignorePrevStateUnknown":false,"ignorePrevStateUnavailable":false,"ignoreCurrentStateUnknown":false,"ignoreCurrentStateUnavailable":false,"outputProperties":[{"property":"action","propertyType":"msg","value":"3","valueType":"num"}],"x":120,"y":460,"wires":[["2944f56e19118bea"],[]],"info":"Récupére le statut du bouton stop du volet\r\n\r\nEntité:\r\n\r\ninput_boolean.volets_stop_bureau"},{"id":"2944f56e19118bea","type":"change","z":"575207865d1e30df","g":"cf0c264bd8d76173","name":"Valeurs communes","rules":[{"t":"set","p":"device_id","pt":"msg","to":"Le votre","tot":"str"},{"t":"set","p":"time","pt":"msg","to":"","tot":"date"},{"t":"set","p":"id","pt":"msg","to":"bureau","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":710,"y":400,"wires":[["3435c1ac287473d5","ef8678a601244c43"]],"info":"Injecte les valeurs pour les variables suivantes:\r\n\r\n    device_id: Id du module à piloter\r\n\r\n    time: un timestamp\r\n\r\n    Id: le nom de la pièce où est situé l'entité à piloter."},{"id":"5d0d3ef7668a4ccc","type":"time-inject","z":"575207865d1e30df","g":"cf0c264bd8d76173","name":"","nameInt":"timestamp ↻1min","positionConfig":"403a6e4bd797cb6e","props":[{"p":"","pt":"msgPayload","v":"","vt":"date","o":"","oT":"none","oM":"60000","f":0,"fS":0,"fT":"UNIX timestamp (ms)","fI":"0","next":true,"days":"*","months":"*","onlyOddDays":false,"onlyEvenDays":false,"onlyOddWeeks":false,"onlyEvenWeeks":false}],"injectTypeSelect":"interval","intervalCount":"1","intervalCountType":"num","intervalCountMultiplier":60000,"cron":"","cronType":"cronexpr","time":"","timeType":"entered","offset":0,"offsetType":"none","offsetMultiplier":60000,"timeEnd":"","timeEndType":"entered","timeEndOffset":0,"timeEndOffsetType":"none","timeEndOffsetMultiplier":60000,"timeDays":"*","timeOnlyOddDays":false,"timeOnlyEvenDays":false,"timeOnlyOddWeeks":false,"timeOnlyEvenWeeks":false,"timeMonths":"*","timedatestart":"","timedateend":"","property":"","propertyType":"none","propertyCompare":"true","propertyThreshold":"","propertyThresholdType":"num","timeAlt":"","timeAltType":"entered","timeAltDays":"*","timeAltOnlyOddDays":false,"timeAltOnlyEvenDays":false,"timeAltOnlyOddWeeks":false,"timeAltOnlyEvenWeeks":false,"timeAltMonths":"*","timeAltOffset":0,"timeAltOffsetType":"none","timeAltOffsetMultiplier":60000,"once":false,"onceDelay":0.1,"recalcTime":2,"x":140,"y":580,"wires":[["ed4b55973ab44531"]]},{"id":"ed4b55973ab44531","type":"api-current-state","z":"575207865d1e30df","g":"cf0c264bd8d76173","name":"Matin auto","server":"8ba7aec4.1022e","version":3,"outputs":2,"halt_if":"on","halt_if_type":"str","halt_if_compare":"is","entity_id":"input_boolean.volets_auto_matin_etat_bureau","state_type":"str","blockInputOverrides":false,"outputProperties":[{"property":"action","propertyType":"msg","value":"5","valueType":"num"}],"for":"0","forType":"num","forUnits":"minutes","override_topic":false,"state_location":"payload","override_payload":"msg","entity_location":"data","override_data":"msg","x":350,"y":580,"wires":[["2944f56e19118bea"],[]],"info":"La fonction d'ouverture automatique du volet le matin\r\n\r\nLa fonction est activée toutes les minutes afin d'entrer dans la plage d'ouverture solaire du noeud \"Plage Matin\""},{"id":"774b0f631c34df85","type":"api-current-state","z":"575207865d1e30df","g":"cf0c264bd8d76173","name":"Soir auto","server":"8ba7aec4.1022e","version":3,"outputs":2,"halt_if":"on","halt_if_type":"str","halt_if_compare":"is","entity_id":"input_boolean.volets_auto_soir_etat_bureau","state_type":"str","blockInputOverrides":false,"outputProperties":[{"property":"action","propertyType":"msg","value":"6","valueType":"num"}],"for":"0","forType":"num","forUnits":"minutes","override_topic":false,"state_location":"payload","override_payload":"msg","entity_location":"data","override_data":"msg","x":360,"y":640,"wires":[["2944f56e19118bea"],[]],"info":"La fonction d'ouverture automatique du volet le soir\r\n\r\nLa fonction est activée toutes les minutes afin d'entrer dans la plage d'ouverture solaire du noeud \"Plage soir\""},{"id":"f16a017b0ec4ef0b","type":"link in","z":"575207865d1e30df","g":"cf0c264bd8d76173","name":"link in 57","links":["4806e36ad01b37b4"],"x":65,"y":700,"wires":[["838abe6fd5394eba"]]},{"id":"3435c1ac287473d5","type":"link out","z":"575207865d1e30df","g":"cf0c264bd8d76173","name":"link out 79","mode":"link","links":["e5524eec8adfea50"],"x":895,"y":400,"wires":[]},{"id":"5574b4a7301e429b","type":"inject","z":"575207865d1e30df","g":"cf0c264bd8d76173","name":"Refresh statut","props":[{"p":"action","v":"7","vt":"num"}],"repeat":"300","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":140,"y":300,"wires":[["2944f56e19118bea"]]},{"id":"4ed1092604d4f241","type":"time-inject","z":"575207865d1e30df","g":"cf0c264bd8d76173","name":"","nameInt":"timestamp ↻1min","positionConfig":"403a6e4bd797cb6e","props":[{"p":"","pt":"msgPayload","v":"","vt":"date","o":"","oT":"none","oM":"60000","f":0,"fS":0,"fT":"UNIX timestamp (ms)","fI":"0","next":true,"days":"*","months":"*","onlyOddDays":false,"onlyEvenDays":false,"onlyOddWeeks":false,"onlyEvenWeeks":false}],"injectTypeSelect":"interval","intervalCount":"1","intervalCountType":"num","intervalCountMultiplier":60000,"cron":"","cronType":"cronexpr","time":"","timeType":"entered","offset":0,"offsetType":"none","offsetMultiplier":60000,"timeEnd":"","timeEndType":"entered","timeEndOffset":0,"timeEndOffsetType":"none","timeEndOffsetMultiplier":60000,"timeDays":"*","timeOnlyOddDays":false,"timeOnlyEvenDays":false,"timeOnlyOddWeeks":false,"timeOnlyEvenWeeks":false,"timeMonths":"*","timedatestart":"","timedateend":"","property":"","propertyType":"none","propertyCompare":"true","propertyThreshold":"","propertyThresholdType":"num","timeAlt":"","timeAltType":"entered","timeAltDays":"*","timeAltOnlyOddDays":false,"timeAltOnlyEvenDays":false,"timeAltOnlyOddWeeks":false,"timeAltOnlyEvenWeeks":false,"timeAltMonths":"*","timeAltOffset":0,"timeAltOffsetType":"none","timeAltOffsetMultiplier":60000,"once":false,"onceDelay":0.1,"recalcTime":2,"x":140,"y":640,"wires":[["774b0f631c34df85"]]},{"id":"1dca3aa3afcef4d4","type":"server-state-changed","z":"575207865d1e30df","g":"cf0c264bd8d76173","name":"Poucentage d'ouverture","server":"8ba7aec4.1022e","version":5,"outputs":1,"exposeAsEntityConfig":"","entityId":"input_number.volets_niveau_bureau","entityIdType":"exact","outputInitially":false,"stateType":"str","ifState":"","ifStateType":"str","ifStateOperator":"is","outputOnlyOnStateChange":true,"for":"0","forType":"num","forUnits":"minutes","ignorePrevStateNull":false,"ignorePrevStateUnknown":false,"ignorePrevStateUnavailable":false,"ignoreCurrentStateUnknown":false,"ignoreCurrentStateUnavailable":false,"outputProperties":[{"property":"taux","propertyType":"msg","value":"","valueType":"entityState"},{"property":"action","propertyType":"msg","value":"4","valueType":"str"}],"x":140,"y":520,"wires":[["2944f56e19118bea"]],"info":"Récupére le pourcentage d'ouverture désiré du volet\r\n\r\nEntité:\r\n\r\ninput_number.volets_niveau_bureau"},{"id":"838abe6fd5394eba","type":"change","z":"575207865d1e30df","g":"cf0c264bd8d76173","name":"Plage d'azimut","rules":[{"t":"set","p":"azi_min","pt":"msg","to":"160","tot":"num"},{"t":"set","p":"azi_max","pt":"msg","to":"226","tot":"num"}],"action":"","property":"","from":"","to":"","reg":false,"x":340,"y":700,"wires":[["2944f56e19118bea"]],"info":"Utilisé par la fonction Azimut, il récupére la valeur max et min de la plage d'azimut pour cette fenêtre"},{"id":"8ba7aec4.1022e","type":"server","name":"Home Assistant","version":5,"addon":true,"rejectUnauthorizedCerts":true,"ha_boolean":"y|yes|true|on|home|open","connectionDelay":true,"cacheJson":true,"heartbeat":false,"heartbeatInterval":30,"areaSelector":"friendlyName","deviceSelector":"friendlyName","entitySelector":"friendlyName","statusSeparator":"at: ","statusYear":"hidden","statusMonth":"short","statusDay":"numeric","statusHourCycle":"h23","statusTimeFormat":"h:m","enableGlobalContextStore":true},{"id":"403a6e4bd797cb6e","type":"position-config","name":"Domicile ","isValide":"true","angleType":"deg","timeZoneOffset":"99","timeZoneDST":"0","stateTimeFormat":"3","stateDateFormat":"12","contextStore":""}]
Le sous-flow
[{"id":"d8d288c742b5c81b","type":"subflow","name":"API Tuya iot","info":"# Gestion des APIs TUYA Iot\r\n\r\nAfin de faire fonctionner ce subflow, il faut lui passer le message de structure:\r\n\r\nmsg.tuya_api.client_id\r\nmsg.tuya_api.time un timestamp\r\nmsg.tuya_api.device_id\r\nmsg.tuya_api.user_id\r\nmsg.tuya_api.commande commande aiguillant entre ordre de configuration ou relevé de statut de l'entité.\r\nmsg.tuya_api.ordre ordre à passer à l'entité\r\n\r\n","category":"smarthome","in":[{"x":100,"y":220,"wires":[{"id":"cc34878229ba459b"},{"id":"22c9308e64d572f2"}]}],"out":[{"x":1840,"y":620,"wires":[{"id":"eb7d0fb48dfeea11","port":0}]}],"env":[],"meta":{},"color":"#DDAA99"},{"id":"cfd6cdedc4113f75","type":"group","z":"d8d288c742b5c81b","style":{"stroke":"#999999","stroke-opacity":"1","fill":"none","fill-opacity":"1","label":true,"label-position":"nw","color":"#a4a4a4"},"nodes":["ee971e8557275277","6222843a323ae47f","c730d9c21c85b6c1","80f2ce055feca5f9","0d8eb54a529bf85e","08e4cb4a36124ade"],"x":374,"y":299,"w":1332,"h":162},{"id":"4dfe7d10f3f1a3fb","type":"group","z":"d8d288c742b5c81b","style":{"stroke":"#999999","stroke-opacity":"1","fill":"none","fill-opacity":"1","label":true,"label-position":"nw","color":"#a4a4a4"},"nodes":["6b3e51e7263bd40c","046627bc0bc11fbb","cc34878229ba459b","f3818dca4e177f69","0ac904677470531b","bfb85005e1a20a62","22c9308e64d572f2"],"x":294,"y":39,"w":1192,"h":222},{"id":"6565106fc2673045","type":"group","z":"d8d288c742b5c81b","style":{"stroke":"#999999","stroke-opacity":"1","fill":"none","fill-opacity":"1","label":true,"label-position":"nw","color":"#a4a4a4"},"nodes":["4ad7112320d38417","eb7d0fb48dfeea11","174a610c49d94236","6f079306406b226b","b7dac392bb492edb"],"x":374,"y":539,"w":892,"h":142},{"id":"6b3e51e7263bd40c","type":"function","z":"d8d288c742b5c81b","g":"4dfe7d10f3f1a3fb","name":"Connexion1","func":"var url = \"https://openapi.tuyaeu.com/v1.0/token?grant_type=1\";\nvar t = msg.tuya_api.time;\nvar sign = msg.payload;\nvar client_id = msg.tuya_api.client_id;\n\nmsg.headers ={\n \"sign_method\": \"HMAC-SHA256\",\n \"client_id\" : client_id,\n \"t\": t.toString(),\n \"sign\": sign.toUpperCase(),\n },\n \n msg.payload = '';\n msg.url = url;\n msg.method = \"GET\";\n msg.tuya_api.sign_secret = sign;\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":910,"y":220,"wires":[["046627bc0bc11fbb"]]},{"id":"046627bc0bc11fbb","type":"http request","z":"d8d288c742b5c81b","g":"4dfe7d10f3f1a3fb","name":"","method":"use","ret":"obj","paytoqs":"ignore","url":"","tls":"","persist":false,"proxy":"","authType":"","x":1110,"y":220,"wires":[["0ac904677470531b"]]},{"id":"cc34878229ba459b","type":"function","z":"d8d288c742b5c81b","g":"4dfe7d10f3f1a3fb","name":"Create signStr","func":"let client_id = msg.tuya_api.client_id;\nlet t = msg.tuya_api.time;\n\nnode.status({fill:\"red\",shape:\"ring\",text:client_id});\nlet method = \"GET\";\nlet sign_url = \"/v1.0/token?grant_type=1\";\n\n// Couldn't get nodered to process an empty string so this is a hash of an empty file\nlet content_hash = \"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855\";\nlet string_to_sign = method+\"\\n\"+content_hash+\"\\n\"+\"\"+\"\\n\"+sign_url;\nmsg.payload = client_id+t+string_to_sign;\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":480,"y":220,"wires":[["f3818dca4e177f69"]]},{"id":"f3818dca4e177f69","type":"hmac","z":"d8d288c742b5c81b","g":"4dfe7d10f3f1a3fb","name":"Sign signStr with secret","algorithm":"HmacSHA256","key":"58fb24515a07454886120147b4225450","x":690,"y":220,"wires":[["6b3e51e7263bd40c"]]},{"id":"0ac904677470531b","type":"function","z":"d8d288c742b5c81b","g":"4dfe7d10f3f1a3fb","name":"Extract Token from Response","func":"var data = msg.payload;\nvar access = data.result.access_token;\nvar refresh = data.result.refresh_token;\n\n//msg.creds = {};\nmsg.tuya_api.access_token = access\nmsg.tuya_api.refresh_token = refresh;\n\nmsg.payload = msg.tuya_api.ordre;\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":1340,"y":220,"wires":[["f66948c2c5ba3d70"]]},{"id":"f66948c2c5ba3d70","type":"function","z":"d8d288c742b5c81b","name":"Liste des opérations","func":"if (msg.tuya_api.commande == 0){\n return [msg,null];\n} else if (msg.tuya_api.commande == 1){\n return [null,msg];\n}else {\n node.warn(\"La valeur de la commande n'est pas connue\");\n}","outputs":2,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":200,"y":460,"wires":[["0d8eb54a529bf85e","2064e8ad64cd37f6"],["6f079306406b226b","f30fdead3ce3856b"]],"outputLabels":["0","1"]},{"id":"ee971e8557275277","type":"function","z":"d8d288c742b5c81b","g":"cfd6cdedc4113f75","name":"Connexion2","func":"let device_id = msg.tuya_api.device_id;\nlet url = \"https://openapi.tuyaeu.com/v1.0/devices/\" + device_id + \"/commands\";\nlet t = msg.time;\nlet client_id = msg.tuya_api.client_id;\nlet access_token = msg.tuya_api.access_token;\nlet sign = msg.payload;\n\nmsg.headers ={\n \"sign_method\": \"HMAC-SHA256\",\n \"client_id\" : client_id,\n \"t\": t.toString(),\n \"mode\" : \"cors\",\n \"Content-Type\": \"application/json\",\n \"sign\": sign.toUpperCase(),\n \"access_token\" : access_token,\n },\n\nmsg.payload = msg.tuya_api.ordre;\nmsg.url = url;\nmsg.method = \"POST\";\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":1430,"y":420,"wires":[["6222843a323ae47f"]]},{"id":"6222843a323ae47f","type":"http request","z":"d8d288c742b5c81b","g":"cfd6cdedc4113f75","name":"","method":"use","ret":"obj","paytoqs":"ignore","url":"","tls":"","persist":false,"proxy":"","insecureHTTPParser":false,"authType":"","senderr":false,"headers":[],"x":1610,"y":420,"wires":[["9c338d50728a3fc8","c75f94b3825f07bd"]]},{"id":"c730d9c21c85b6c1","type":"function","z":"d8d288c742b5c81b","g":"cfd6cdedc4113f75","name":"Create signStr","func":"//let creds = flow.get(\"tuya\");\nlet access_token = msg.tuya_api.access_token;\nlet device_id = msg.tuya_api.device_id;\nlet t = msg.tuya_api.time;\nlet client_id = msg.tuya_api.client_id;\n\nlet method = \"POST\";\nlet sign_url = \"/v1.0/devices/\" + device_id + \"/commands\";\nlet content_hash = msg.payload;\n\nlet string_to_sign = method+\"\\n\"+content_hash+\"\\n\"+\"\"+\"\\n\"+sign_url;\nlet signStr = client_id + access_token + t + string_to_sign;\n\nmsg.payload = signStr;\n//msg.time = msg.time;\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":940,"y":420,"wires":[["80f2ce055feca5f9"]]},{"id":"80f2ce055feca5f9","type":"hmac","z":"d8d288c742b5c81b","g":"cfd6cdedc4113f75","name":"Sign signStr with secret","algorithm":"HmacSHA256","key":"58fb24515a07454886120147b4225450","x":1190,"y":420,"wires":[["ee971e8557275277"]]},{"id":"0d8eb54a529bf85e","type":"digest","z":"d8d288c742b5c81b","g":"cfd6cdedc4113f75","name":"Hash the body data","algorithm":"SHA256","x":710,"y":420,"wires":[["c730d9c21c85b6c1"]]},{"id":"08e4cb4a36124ade","type":"comment","z":"d8d288c742b5c81b","g":"cfd6cdedc4113f75","name":"Donner un ordre","info":"","x":480,"y":340,"wires":[]},{"id":"bfb85005e1a20a62","type":"comment","z":"d8d288c742b5c81b","g":"4dfe7d10f3f1a3fb","name":"Récupérer un token","info":"","x":490,"y":160,"wires":[]},{"id":"4ad7112320d38417","type":"function","z":"d8d288c742b5c81b","g":"6565106fc2673045","name":"Connexion3","func":"let device_id = msg.tuya_api.device_id;\nlet url = \"https://openapi.tuyaeu.com/v1.0/devices/\" + device_id + \"/status\";\nlet t = msg.tuya_api.time;\nlet method = \"GET\";\nlet client_id = msg.tuya_api.client_id;\n//let creds = flow.get(\"tuya\");\nlet token = msg.tuya_api.access_token;\n//let sign = msg.payload;\nlet sign = msg.payload;\n\nmsg.headers ={\n \"sign_method\": \"HMAC-SHA256\",\n \"client_id\" : client_id,\n \"t\": t.toString(),\n \"mode\" : \"cors\",\n \"Content-Type\": \"application/json\",\n \"sign\": sign.toUpperCase(),\n \"access_token\" : token\n },\n\n msg.payload = '';\n msg.url = url;\n msg.method = \"GET\";\n \nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":970,"y":640,"wires":[["eb7d0fb48dfeea11"]]},{"id":"eb7d0fb48dfeea11","type":"http request","z":"d8d288c742b5c81b","g":"6565106fc2673045","name":"","method":"use","ret":"obj","paytoqs":"ignore","url":"","tls":"","persist":false,"proxy":"","authType":"","x":1170,"y":640,"wires":[[]]},{"id":"174a610c49d94236","type":"comment","z":"d8d288c742b5c81b","g":"6565106fc2673045","name":"Get Status Of Device","info":"","x":500,"y":580,"wires":[]},{"id":"9c338d50728a3fc8","type":"debug","z":"d8d288c742b5c81b","d":true,"name":"debug 309","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":1870,"y":420,"wires":[]},{"id":"6f079306406b226b","type":"function","z":"d8d288c742b5c81b","g":"6565106fc2673045","name":"Create signStr","func":"let access_token = msg.tuya_api.access_token;\nlet device_id = msg.tuya_api.device_id;\nlet t = msg.tuya_api.time;\nlet client_id = msg.tuya_api.client_id;\n\nlet method = \"GET\";\nlet sign_url = \"/v1.0/devices/\" + device_id + \"/status\";\nlet content_hash = \"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855\";\n\nlet string_to_sign = method + \"\\n\" + content_hash + \"\\n\" + \"\" + \"\\n\" + sign_url;\nlet signStr = client_id + access_token + t + string_to_sign;\n\nmsg.payload = signStr;\n//msg.time = msg.tuya_api.time;\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":480,"y":640,"wires":[["b7dac392bb492edb"]]},{"id":"b7dac392bb492edb","type":"hmac","z":"d8d288c742b5c81b","g":"6565106fc2673045","name":"Sign signStr with secret","algorithm":"HmacSHA256","key":"58fb24515a07454886120147b4225450","x":710,"y":640,"wires":[["4ad7112320d38417"]]},{"id":"22c9308e64d572f2","type":"debug","z":"d8d288c742b5c81b","d":true,"g":"4dfe7d10f3f1a3fb","name":"debug 336","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":390,"y":80,"wires":[]},{"id":"2064e8ad64cd37f6","type":"debug","z":"d8d288c742b5c81b","d":true,"name":"debug 337","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":310,"y":340,"wires":[]},{"id":"f30fdead3ce3856b","type":"debug","z":"d8d288c742b5c81b","d":true,"name":"debug 338","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":250,"y":620,"wires":[]},{"id":"c75f94b3825f07bd","type":"delay","z":"d8d288c742b5c81b","name":"","pauseType":"delay","timeout":"2","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"allowrate":false,"outputs":1,"x":1260,"y":500,"wires":[["6f079306406b226b"]]}]
Avant d’entrer dans les détails, sachez que chaque nœud contient une description de son fonctionnement. Je pense pas en avoir oublié. Si tel était le cas merci de me le signaler que je corrige/complète.
1. Global Settings CLICK On Start TAB
C’est le premier nœud à corriger. La procédure pour récupérer les valeurs est Ici.
2. Taux Ouverture
C’est dans cette fonction que vous gérez le niveau d’ouverture du volet en fonction de sa position dans le ciel. Elle est utilisé par la fonction Azimut.
3. Valeurs communes
Stocke les valeurs propres à ce volet. Il est impératif de changer les valeurs à l’intérieur pour qu’elles correspondent à votre environnement.
4. Plage d’Azimut
Détermine qu’elle sera la plage d’Azimut pendant laquelle la fonction s’enclenchera.
Une dernière chose le groupe Bureau est à dupliquer et modifier pour chaque volet.
Voila en espérant que cela pourra servir. Je me permets 2 bémols au fonctionnement
- Il peut arriver que le volet ne réagisse pas, c’est certainement que le module s’est « perdu » pour je ne sais quelle raison. Dans ce cas, enclencher l’ordre d’Ouverture ou de Fermeture attendre qu’il claque puis relancer c’est reparti.
- L’azimut étant mouvant en fonction de l’année, les valeurs sont à recalculer régulièrement aide. Je travaille sur une fonction qui calculera la position azimut en fonction d’une valeur de référence. Si jamais j’y arrive, je l’ajouterai à ce post.
Voilà n’hésitez pas à me faire vos remarques si certaines choses ne sont pas claires ou si vous voulez plus d’explication.
Passer une bonne journée