|
#importation des librairies
|
|
import math
|
|
import serial
|
|
import time
|
|
import sys
|
|
|
|
import numpy as np
|
|
|
|
import matplotlib.pyplot as plt
|
|
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2Tk
|
|
from matplotlib.figure import Figure
|
|
import matplotlib.animation as animation
|
|
from matplotlib import style
|
|
|
|
from tkinter import *
|
|
from tkinter.filedialog import askopenfilename
|
|
import tkinter as tk
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#définition de la police
|
|
LARGE_FONT=("Verdana",16)
|
|
#on détermine le style du graphique (avec fond gris)
|
|
style.use("ggplot")
|
|
|
|
|
|
|
|
##### ESSAI FIGURE EN TEMPS RÉEL #####
|
|
|
|
# #on définit la taille de la figure
|
|
# f = Figure(figsize = (5,5), dpi = 100)
|
|
# #ajout de la figure avec subplot (111 = figure 1 par 1 et figure numéro 1)
|
|
# a = f.add_subplot(111)
|
|
# #on renseignes les données
|
|
#
|
|
#
|
|
# def animate(i):
|
|
# pullData = open("data","r").read()
|
|
# dataList = pullData.split('\n')
|
|
# xList = []
|
|
# for eachLine in dataList:
|
|
# if len(eachLine) >1:
|
|
# x=eachLine
|
|
# xList.append(int(x))
|
|
# a.clear()
|
|
# a.plot(xList)
|
|
|
|
|
|
|
|
#Création de la classe Graphique
|
|
class Graphique(tk.Tk):
|
|
|
|
|
|
#initialisateur appelé automatiquement après qu'un objet ait été créé
|
|
#on donne l'état de départ
|
|
#accepet des paramètres, self doit être le premier paramètre
|
|
#self = l'objet cible, c'est une variable qui contient une référence vers l'objet en cours de création
|
|
def __init__(self, *args, **kwargs):
|
|
|
|
|
|
#on initalise la fenêtre
|
|
tk.Tk.__init__(self, *args, **kwargs)
|
|
# défintion du titre
|
|
tk.Tk.wm_title(self, "Graphique")
|
|
|
|
container = tk.Frame(self)
|
|
container.pack(side="top", fill="both", expand = True)
|
|
container.grid_rowconfigure(0,weight=1)
|
|
container.grid_columnconfigure(0,weight=1)
|
|
|
|
self.frames = {}
|
|
|
|
for F in (StartPage, PageOne, PageTwo, PageThree):
|
|
frame = F(container,self)
|
|
self.frames[F] = frame
|
|
frame.grid(row=0, column=0, sticky="nsew")
|
|
self.show_frame(StartPage)
|
|
|
|
def show_frame(self,cont):
|
|
frame = self.frames[cont]
|
|
frame.tkraise()
|
|
|
|
|
|
#page d'accueil
|
|
class StartPage(tk.Frame):
|
|
|
|
def __init__(self, parent, controller):
|
|
tk.Frame.__init__(self,parent)
|
|
#inscription
|
|
label = tk.Label(self,text="Bienvenue", font=LARGE_FONT)
|
|
#placement du label à la ligne 2, colonne 6
|
|
label.grid(row = 2, column=6)
|
|
#on créé un bouton qui va permettre de rediriger vers l'affichage de la température sur une autre page
|
|
button = tk.Button(self, text = "Afficher la température", command = lambda: controller.show_frame(PageOne))
|
|
#Placement du bouton
|
|
button.grid(row = 3, column = 6)
|
|
#bouton qui redirige vers la page de control des Leds
|
|
button2 = tk.Button(self, text = "Contrôler les LEDs", command=lambda: controller.show_frame(PageTwo))
|
|
#placement du bouton
|
|
button2.grid(row=4, column = 6)
|
|
#bouton qui redirige vers la page d'un formulairre
|
|
button3 = tk.Button(self, text = "Remplir un formulaire", command=lambda: controller.show_frame(PageThree))
|
|
button3.grid(row=5, column = 6)
|
|
#en haut, on place un menu
|
|
zoneMenu = Frame(self, borderwidth=3, bg='#557788')
|
|
zoneMenu.grid(row=0, column = 0)
|
|
#on créé chaque onglet du menu :
|
|
|
|
# Création de l'onglet Fichier
|
|
menuFichier = Menubutton(zoneMenu, text = 'Fichier', width='20', borderwidth=2, bg='gray', activebackground='darkorange', relief = RAISED)
|
|
menuFichier.grid(row=0, column=0)
|
|
|
|
# Création de l'onglet Edition
|
|
menuEdit = Menubutton(zoneMenu, text='Editer', width='20', borderwidth=2, bg='gray', activebackground='darkorange',relief = RAISED)
|
|
menuEdit.grid(row=0,column=1)
|
|
|
|
# Création de l'onglet Format
|
|
menuFormat = Menubutton(zoneMenu, text='Format', width='20', borderwidth=2, bg='gray', activebackground='darkorange',relief = RAISED)
|
|
menuFormat.grid(row=0,column=2)
|
|
|
|
menuAffichage = Menubutton(zoneMenu, text='Affichage', width='20', borderwidth=2, bg='gray', activebackground='darkorange',relief = RAISED)
|
|
menuAffichage.grid(row=0,column=3)
|
|
|
|
|
|
#création des fonctions servant aux différents onglets
|
|
# fonctions de l'onglet Affichage, elles changent juste la couleur du fonc
|
|
def fondClair():
|
|
self.configure(bg = 'pink')
|
|
|
|
def fondSombre():
|
|
self.configure(bg= 'black')
|
|
|
|
# création d'un menu déroulant
|
|
Menu(menuAffichage,tearoff=0)
|
|
menuDeroulant1 = Menu(menuAffichage)
|
|
menuDeroulant1.add_command(label='Fond clair', command = fondClair)
|
|
menuDeroulant1.add_command(label='Fond sombre', command = fondSombre)
|
|
|
|
# attribution du menu déroulant au menu menuAffichage
|
|
menuAffichage.configure(menu=menuDeroulant1)
|
|
|
|
|
|
|
|
|
|
#fonctions de l'onglet Fichier
|
|
#on peut ouvrir un fichier, afficher un message
|
|
|
|
#on ouvre un fichier de l'ordinateur
|
|
def openFile():
|
|
file = askopenfilename(title="Choisir un fichier à ouvrir",filetypes=[("PNG image", ".png"), ("GIF image", ".gif"), ("All files", ".*")])
|
|
print( file )
|
|
|
|
#cette fonction afficher seulement "Menu Clicked" sur le terminal
|
|
def doSomething(fenetre):
|
|
print("Menu clicked")
|
|
|
|
#cette fonction affiche un message sur l'interface
|
|
#il est seulement marqué ce qu'ily a entre parenthèses
|
|
def doAbout(fenetre):
|
|
messagebox.showinfo("My title", "My message")
|
|
#
|
|
#affichage du menu Fichier
|
|
Menu(menuFichier, tearoff=0)
|
|
menuDeroulant2=Menu(menuFichier)
|
|
#on détaille chaque possibilité de l'onglet Fichier
|
|
#chaque possibilité est reliée à une fonction
|
|
menuDeroulant2.add_command(label="New", command= doSomething)
|
|
menuDeroulant2.add_command(label="Open", command= openFile)
|
|
menuDeroulant2.add_command(label="Save", command= doSomething)
|
|
menuDeroulant2.add_separator()
|
|
menuDeroulant2.add_command(label="Exit", command=self.quit)
|
|
|
|
menuFichier.configure(menu=menuDeroulant2)
|
|
|
|
|
|
#Deuxième page de l'interface qui va permettre d'afficher la température
|
|
class PageOne(tk.Frame) :
|
|
#fonction d'initialisation
|
|
def __init__(self,parent,controller):
|
|
tk.Frame.__init__(self,parent)
|
|
#on affiche un label
|
|
label = tk.Label(self, text="Graphe de la température", font=LARGE_FONT)
|
|
label.pack(pady=10, padx=10)
|
|
|
|
|
|
# res=entree1.get()
|
|
# print(res)
|
|
#fonction de controle qui va permettre d'actionner la prise de température et son affichage
|
|
def control():
|
|
#on précise le port, ici l'arduino est /dev/ttyACM0
|
|
ser = serial.Serial('/dev/ttyACM0',9600);
|
|
print(ser)
|
|
|
|
#Réception et stockage des données
|
|
#on prend ici en compte données
|
|
|
|
#cette fonction se déclenche lorsque l'on appuie sur le bouton Actionner
|
|
def getEntry():
|
|
#On récupère le texte entré par l'utilisateur afin de savoir combien de points il veut sur sa courbe
|
|
res = entree1.get()
|
|
print(res)
|
|
|
|
#on initialise un tableau dans lequel les données vont arriver
|
|
rawdata =[]
|
|
compt = 0;
|
|
|
|
#on remplit le tableau avec les valeurs du fichier texte
|
|
#on prend on considérations les n valeurs, n étant le nombre décidé par l'utilisateur
|
|
while (compt<int(res)):
|
|
#on rremplit le tableau rawdata par les valeurs du fichier texte
|
|
rawdata.append(str(ser.readline()))
|
|
#on rajoute 1 au compteur jusqu'a ce qu'il atteigne res (la valeur décidée par l'utilisateur)
|
|
compt+=1
|
|
#on affiche le tableau rawdata sur le terminal
|
|
print(rawdata);
|
|
|
|
#les valeurs sur le terminal s'affiche de cette manière :
|
|
#["b'val1\\n'", "b'val2\\n'", "b'val\\n'"]
|
|
#On veut un tableau plus clair, sans le b ni le \\n
|
|
#Pour cela, on écrit la fonction nettoie qui va permettre d'afficher un tableau :['val1', 'val2', 'val3']
|
|
def nettoie(L):
|
|
#on initialise un nouveau tableau
|
|
newL=[]
|
|
#jusqu'a ce qu'on atteigne la fin de la longueur de notre tableau rawdata
|
|
for i in range(len(L)):
|
|
#on réduit le b et le \\n
|
|
temp=L[i][2:]
|
|
#on remplit le nouveau tableau newL avec la valeur "nettoyée"
|
|
newL.append(temp[:-5])
|
|
#on retourne le nouveau tableau
|
|
return newL
|
|
|
|
#on appelle la fonction nettoie
|
|
cleandata=nettoie(rawdata)
|
|
#on écrit le nouveau tableau dans le terminal
|
|
print(cleandata)
|
|
|
|
#on veut maintenant remplir le fichier texte des valeurs prises
|
|
def write(L):
|
|
#on ouvre le fichier data.txt en mode écriture (w)
|
|
file = open("data.txt", mode="w")
|
|
#on parcourt notre tableau et on ajoute chaque case à chaque ligne du fichierr
|
|
for i in range(len(L)):
|
|
file.write(L[i]+'\n')
|
|
#on ferme le fichier
|
|
file.close()
|
|
|
|
#on appelle la fonction qui va permettre d'écrire dans le fichier texte
|
|
write(cleandata)
|
|
|
|
#on définit la taille de la figure
|
|
f = Figure(figsize = (1,0.5), dpi = 25)
|
|
|
|
#ajout de la figure avec subplot (111 = figure 1 par 1 et figure numéro 1)
|
|
a = f.add_subplot(111)
|
|
#oon affiche la figure, on prend en compte le fichier data.txt
|
|
#ne pas oublier le delimiter, ce qui va séparer chaque valeur, dans ce cas ci c'est un retour à la ligne, donc un espace
|
|
a.plot(np.loadtxt("data.txt",delimiter=' ',unpack=True))
|
|
|
|
#on affiche le Graphe avec en paramètre notre figure f définie avant
|
|
#on appelle canvas
|
|
canvas = FigureCanvasTkAgg(f, self)
|
|
canvas.draw()
|
|
#on détermine l'emplacement du graphe s sur la figure
|
|
canvas.get_tk_widget().pack(side = tk.TOP, fill=tk.BOTH)
|
|
#on affiche un menu en bas de la page avec diverses focntionnalités donc la possibilité d'eregistrer le fichier
|
|
toolbar = NavigationToolbar2Tk(canvas, self)
|
|
toolbar.update()
|
|
#on place la figure, ici elle est placée sur la gauche
|
|
canvas._tkcanvas.pack(side = tk.LEFT, fill=tk.BOTH, expand= True)
|
|
|
|
|
|
|
|
#on affiche un texte avec label pour demander à l'utilisateur combien de points il souhaite mesurer
|
|
texte1 = tk.Label(self, text = "Combien de points souhaitez-vous mesurer ? ", font=LARGE_FONT)
|
|
#on place ce texte
|
|
texte1.pack()
|
|
#espace où l'utilisateur peut rentrer la valeur qu'il souhaite
|
|
#petit problème de placement, cette case se place tout en bas de la page et pas nécessairement à coté du label
|
|
entree1 = Entry()
|
|
#on place cette entrée
|
|
entree1.pack()
|
|
#on met en place un bouton valider où l'utilisateur vaide son choix
|
|
#ce bouton se redirigé vers la fonction getEntry() qui va récupérer ce qui a été indiqué dans la case d'écriture
|
|
valid = tk.Button(self, text="Valider", command=getEntry)
|
|
valid.pack()
|
|
|
|
#on place un bouton Actionner
|
|
#lorsque ce bouton est enclenché, il actionne la fonction control qui va réaliser ce qui a été expliqué avant
|
|
#ainsi, on demandera à l'utilisateur combien de points il souhaite
|
|
#puis en appuyant sur le bouton validé, une courbe s'affichera
|
|
#ceci se repète tant que l'on appuie sur le bouton Actionner
|
|
boutonAction = tk.Button(self, text = "Actionner", command = control)
|
|
#placement du bouton Actionner
|
|
boutonAction.pack()
|
|
#un bouton Revenir à l'accueil permet de rediriger l'utilisateur vers la première page que l'on a appelé StartPage
|
|
button1 = tk.Button(self,text = "Revenir à l'accueil", command = lambda: controller.show_frame(StartPage))
|
|
button1.pack()
|
|
#un bouton Controler les Leds permet de rediriger l'utilisateur vers une nouvelle page que l'on a appelé Page Two
|
|
button2 = tk.Button(self,text = "Controler les LEDs", command = lambda: controller.show_frame(PageTwo))
|
|
button2.pack()
|
|
|
|
|
|
|
|
|
|
# ##ICI SE TROUVE UNE FONCTION QUI PERMET DE CALCULER LA MOYENNE DES VALEURS DU FICHIER TEXTE
|
|
# # Ouvrir le fichier en lecture seule
|
|
# file = open('data.txt', "r")
|
|
# # utiliser readlines pour lire toutes les lignes du fichier
|
|
# # La variable "lignes" est une liste contenant toutes les lignes du fichier
|
|
# lines = file.readlines()
|
|
# # fermez le fichier après avoir lu les lignes
|
|
# file.close()
|
|
# # on additionne chaque ligne grâce à nbr pour obtenir la moyenne
|
|
# nbr = 0
|
|
# # long permet de calculer la longueur du fichier
|
|
# long = 0
|
|
# # Itérer sur les lignes
|
|
# for line in lines:
|
|
# #nbr prend la valeur de chaque ligne du fichier et l'ajoute à son compteur
|
|
# nbr += float(line.strip())
|
|
# #on calcule le nombre de lignes du fichier, à chaque itération, long prend +1
|
|
# long+=1
|
|
# #la moyenne vaut toutes la valeurs additionnées entre elles, divisé par le nombre de valeurs (long)
|
|
# moy=nbr/long
|
|
# #on affiche la moyenne grâce à un label
|
|
# moyenne = tk.Label(self, text=("La moyenne de température est",moy), font=LARGE_FONT)
|
|
# moyenne.pack()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#PAGE POUR CONTROLER LES LEDS
|
|
class PageTwo(tk.Frame):
|
|
#initialisation de la page
|
|
def __init__(self, parent, controller):
|
|
tk.Frame.__init__(self,parent)
|
|
#on affiche un label
|
|
label = tk.Label(self, text="Controler les LEDs", font=LARGE_FONT)
|
|
label.pack(pady=10, padx=10)
|
|
#un bouton pour rediriger vers la page d'accueil appelée Start Page dans le code
|
|
button1 = tk.Button(self,text = "Revenir à l'accueil", command = lambda: controller.show_frame(StartPage))
|
|
button1.pack()
|
|
#Bouton pour rediriger l'utilisateur vers la page permettant d'afficher la température, appelée PageOne
|
|
button2 = tk.Button(self,text = "Afficher la température", command = lambda: controller.show_frame(PageOne))
|
|
button2.pack()
|
|
|
|
#on indique le port utilisé
|
|
ser = serial.Serial('/dev/ttyACM0',9600)
|
|
|
|
#une fonction qui permet d'enclencher la led branchée
|
|
def on_button():
|
|
ser.write(b'1')
|
|
|
|
#une fonction qui permet d'éteindre la led
|
|
def off_button():
|
|
ser.write(b'0')
|
|
|
|
|
|
#on définit un bouton
|
|
Button = tk.Button
|
|
#un premier bouton qui lorsqu'on l'active déclenche la fonction on_button permettant d'allumer la led
|
|
btn = Button(self, text="ON", command = on_button)
|
|
#un deuxième bouton qui lorsqu'on l'active déclenche la fonction off_button permettant d'éteindre la led
|
|
btn1 = Button(self,text="OFF", command = off_button)
|
|
#on place ces boutons
|
|
btn.pack()
|
|
btn1.pack()
|
|
|
|
|
|
|
|
#Troisième Page qui permet d'afficher un formulaire
|
|
class PageThree(tk.Frame):
|
|
#initialisation de la page
|
|
def __init__(self,parent,controller):
|
|
tk.Frame.__init__(self,parent)
|
|
#on affiche un label qui écrit Formulaire en titre
|
|
label = tk.Label(self, text = "Formulaire", font = LARGE_FONT)
|
|
label.pack(pady=10, padx=10)
|
|
#un bouton qui permet de revenir à la page d'accueil, StartPage
|
|
button1 = tk.Button(self, text="Back To Home", command=lambda: controller.show_frame(StartPage))
|
|
button1.pack()
|
|
|
|
#on laisse une entrée pour l'utilisateur rentre son nom
|
|
nom = Label(self, text="Nom")
|
|
e0 = Entry(self)
|
|
#on laisse une entrée pour l'utilisateur rentre son prénom
|
|
prenom = Label(self, text="Prenom")
|
|
e = Entry(self)
|
|
nom.pack()
|
|
#on place tous ces champs sur la page
|
|
e0.pack()
|
|
prenom.pack()
|
|
e.pack()
|
|
|
|
|
|
|
|
#Notre interface prend le nom de la classe principale créée au début, c'est à dire Graphique
|
|
app = Graphique()
|
|
#on affiche notre interface avec l'instruction mainloop
|
|
app.mainloop()
|
|
|
|
|
|
|
|
|
|
|
|
##### !!! si lorsque l'on lance le programme python , l'erreur suivante survient -> ValueError: could not convert string to float: ''
|
|
#ouvrir le fichier texte et vérifier qu'une ligne ne soit pas vide, la remplacer avec un chiffre au hasard
|
|
#lors du déclenchement du bouton action, ces valeurs seront remplacées par les valeurs mesurées
|