Bonjour à tous.

1 / Le contexte
Après une première vie professionnelle d'analyste programmeur (C#, php, SQL, Jquerry/javascript) et une pause de 5 ans je me remets à la programmation en apprenant le Python suite à l’acquisition d'un raspberry et de composants électroniques. Comme premier exercice de remise en route j'ai donc branché les composants suivant sur mon raspberry ; capteur de pression et de température, capteur d'humidité, petit écran LCD, LED red green blue ainsi que deux bouton physiques. Lors de l'appuie sur le bouton_1 j'allume ma LED et lui fait changer de couleurs selon un tableau descripteur que je fournis à ma classe LED, un deuxième appuie éteint la LED. En appuyant sur le bouton_2 je récupère pression température et taux d'humidité de mes composants et j'affiche tout ça sur le petit écran LCD agrémenté de la date et de l'heure, un deuxième appuie force un refresh de ces infos.

2/ Mon problème
Je me rends compte que j'ai très mal géré mes Threads.
En effet j'ai du en utiliser car la boucle d'affichage de ma LED ou l'affichage de la météo bloquait le reste de l'exécution de mon programme, logique.
Jusque ici j'ai réussi à lancer l'exécution de ses bouts de code dans des Thread et mon programme ne se bloque donc plus sur l'exécution d'une tache.
Cependant je n'arrive pas à les fermer proprement, si j'appuie plusieurs fois sur le bouton contrôlant ma LED j'ai plusieurs Thread qui tournent en concurrence, ce n'est pas ce que je veux.
Je crois comprendre que je dois hériter la classe threading.Thread afin de coder proprement un événement stop.
Aimant développer selon les standards et selon une architecture propre je me tourne vers vous car je trouve étrange que ma classe LED hérite de threading.Thread.

3/ Un peu de code
Je ne vous montre que ce qui me semble nécessaire à la résolution de mon problème tout en y ajoutant quelques commentaires pour votre compréhension.
Je sais bien qu'il y a des bouts de codes pas logiques/inutile/mal placés mais comme je vous l'ai dit je développe tout en apprenant et je remanie au fur et à mesure.

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
 
class Led:
    def __init__(self, redpin, greenpin, bluepin, delay, freq, blink_seq):
 
        print("object led constructor")
        self.redPin = redpin
        self.greenPin = greenpin
        self.bluePin = bluepin
        self.delay = delay
        self.freq = freq
        self.blinkSeq = blink_seq
 
        # fixe attributs
        self.redValue = 99
        self.greenValue = 0
        self.blueValue = 33
        self.blinkStatut = False
        self.blinkMod = "none"
 
        GPIO.setup(self.redPin, GPIO.OUT)
        GPIO.setup(self.greenPin, GPIO.OUT)
        GPIO.setup(self.bluePin, GPIO.OUT)
 
        self.redPWM = GPIO.PWM(self.redPin, self.freq)
        self.greenPWM = GPIO.PWM(self.greenPin, self.freq)
        self.bluePWM = GPIO.PWM(self.bluePin, self.freq)
        self.turn_on()
        self.set_color([self.redValue, self.greenValue, self.blueValue])
 
    def blink(self):
        # TODO ne plus commencer le blinkMod = cycle par la couleur rouge mais n'importe laquelle
        print('BLINK')
        if self.blinkStatut:
            self.turn_off()
            self.blinkStatut = False
        else:
            self.turn_on()
            self.blinkStatut = True
            self.redValue = 100  # on initie la LED a rouge pour le cas general
            i = 0
            while self.blinkStatut:
                if type(self.blinkSeq[i]) is int:
                    if self.blinkMod == "color":
                        # apres des sequence en mode couleur on repart de rouge
                        self.redValue = 100
                        self.greenValue = 0
                        self.blueValue = 0
                        self.blinkMod = "cycle"
                    delay = self.delay
                    if self.redValue > 0 and self.blueValue == 0:
                        self.redValue -= self.blinkSeq[i]
                        self.greenValue += self.blinkSeq[i]
                    elif self.greenValue > 0 and self.redValue == 0:
                        self.greenValue -= self.blinkSeq[i]
                        self.blueValue += self.blinkSeq[i]
                    elif self.blueValue > 0 and self.greenValue == 0:
                        self.blueValue -= self.blinkSeq[i]
                        self.redValue += self.blinkSeq[i]
                        if self.blueValue <= 0:
                            i += 1
                        if i > len(self.blinkSeq) - 1:
                            i = 0
 
                    if self.redValue < 0:
                        self.redValue = 0
                    if self.redValue > 100:
                        self.redValue = 100
                    if self.greenValue < 0:
                        self.greenValue = 0
                    if self.greenValue > 100:
                        self.greenValue = 100
                    if self.blueValue < 0:
                        self.blueValue = 0
                    if self.blueValue > 100:
                        self.blueValue = 100
 
                else:
                    self.blinkMod = "color"
                    delay = float(self.blinkSeq[i].split(':')[1])
                    self.redValue = int(self.blinkSeq[i].split(':')[0].split("-")[0])
                    self.greenValue = int(self.blinkSeq[i].split(':')[0].split("-")[1])
                    self.blueValue = int(self.blinkSeq[i].split(':')[0].split("-")[2])
                    i += 1
                    if i > len(self.blinkSeq) - 1:
                        i = 0
 
                self.set_color([self.redValue, self.greenValue, self.blueValue])
                time.sleep(delay)
 
 
GPIO.setmode(GPIO.BCM)
#ci dessous une liste qui sert à indiquer le cycle d'affichage que la LED doit suivre, les int correspondent à un temps pour le mode défilement de couleur, les strings à une couleurs et une durée précise
modelBlink = [1, 5, 10, 10, 10, 20, 20, 20, 33, 33, 33,
              "100-000-000:0.3", "000-100-000:0.3", "000-000-100:0.3",
              "033-066-099:0.3", "99-66-33:0.3", "066-099-033:0.3", "033-099-066:0.3",
              "100-050-000:0.3", "100-000-050:0.3", "000-100-050:0.3", "050-100-000:0.3", "000-050-100:0.3",
              "050-000-100:0.3",
              "005-000-000:0.3", "000-010-000:0.3", "000-000-020:0.3", "030-000-000:0.3", "000-040-000:0.3",
              "000-000-050:0.3", "060-000-000:0.3",
              "000-070-000:0.3", "000-000-080:0.3", "090-000-000:0.3", "000-100-000:0.3",
              33, 33, 33, 20, 20, 20, 10, 10, 5, 1]
led_1 = Led(17, 18, 27, 0.01, 100, modelBlink)
myThreads = {}
 
 
def button_callback1(channel):
 
    print("button_callback1")
 
    if "led" not in myThreads:
        myThreads["led"] = []
    th = threading.Thread(target=led_1.blink)
    th.start()
 
    #ci dessous tentative (malheureuse&inefficace) de fermeture des autres Thread relatifs à la LED
    #Les Threads ne sont pas supprimés de la liste par soucis de débogage
    for elt in myThreads["led"]:
        elt.join()
 
    myThreads["led"].append(th)
 
 
def main():
    GPIO.setup(22, GPIO.IN, GPIO.PUD_UP)  # bouton 1
    GPIO.setup(24, GPIO.IN, GPIO.PUD_UP)  # bouton 2
    GPIO.add_event_detect(22, GPIO.RISING, button_callback1, bouncetime=500)
    GPIO.add_event_detect(24, GPIO.RISING, button_callback2, bouncetime=500)
    LCD1602.init(0x27, 1)  # init(slave address, background light)
    LCD1602.write(0, 0, '      GPIO      ')
    LCD1602.write(0, 1, '     ON AIR     ')
 
 
try:
    main()
    input() # Moyen pas propre que j'ai trouvé pour que mon programme ne se referme pas tout de suite, une suggestion ?
except (KeyboardInterrupt, SystemExit, SystemError):
    destroy()

4/ Ma question
Selon ce que j'ai lu je serait censé faire en sorte que ma classe LED hérite de la classe threading.Thread afin de pouvoir manipuler en marqueur Terminated ainsi que l'ajout d'un événement stop ?
Est ce une bonne pratique ? Ne trouvez vous pas architecturalement parlant bancale le fait que ma classe LED hérite de threading.Thread ?
J'ai intuitivement l'impression que ma classe LED n'est pas le bonne endroit du code ou exécuter la logique relative aux Thread.
D'ailleurs on peut certainement imaginer un cas ou ma classe LED puisse être appelé dans un Thread à part ou dans le Thread principal, à ce moment là le fait de mettre la logique du Thread dans la classe serait bloquant.
Qu'en pensez vous ?
Je suis aussi preneur de tout autre conseil.
Merci beaucoup d'avoir prit le temps de me lire jusque ici.