=====Application serveur de données capteurs=====
#!/usr/bin/python3
# Bertrand Vandeportaele 2019
# https://pymotw.com/2/socket/udp.html
import socket
import sys
import fcntl, errno, os
#pour threads
from threading import Thread, Lock
#à cause de la GIL, ce n'est pas du vrai multithread, lire https://stackoverflow.com/questions/3310049/proper-use-of-mutexes-in-python
#il faudrait utiliser multiprocessing au lieu de threading
#from multiprocessing import Process, Lock
# https://stackoverflow.com/questions/22885775/what-is-the-difference-between-lock-and-rlock
import _thread
import time # https://docs.python.org/fr/3/library/time.html
#création d'une thread par connexion TCP
#https://www.geeksforgeeks.org/socket-programming-multi-threading-python/
'''idée pour identification des messages:
chaque capteur envoie dans le message son adresse mac (et les simulateurs en génère une par capteur simulé)
si la trame passe par un routeur, il n'est pas possible d'avoir l'adresse mac du capteur autrement...
plusieurs messages différents possible par capteur en ajoutant 16 bits en suffixe à l'adresse mac (equivalent numero de port)
requete au serveur de capteur de 2 types possibles
par annuaire de fonctionnalité
par numero d'adresse mac
requete pour récupérer les infos capteur
requete pour récupérer les infos d'identification d'un capteur
TODO: au démarage (et régulièrement) une carte capteur s'identifie dans l'annuaire en indiquant son @MAC + une chaine de caractère qui décrit ce que fournit le capteur
champs, unité
date et heure de compilation du programme
auteur du code
l'annuaire est sauvé dans un fichier texte en local et se reconstruit au fûr et a mesure
on y stocke notamment la date et l'heure de dernière reception du capteur
gérer les changements de formats de données capteur ou le remplacement d'une fonctionnalité
@mac carte joystick: bc:dd:c2:fe:6f:f0
'''
'''todo:
identifier si une donnée capteur est
-seule la dernière est utile
-peut elle être consommée plusieurs fois la même ou pas?
-est au client de vérifier si la donnée a déjà été lue? (auquel cas il faudrait un indice)
-toutes sont utiles en séquence, auquel cas il faut mettre en place une gestion de fifo pour les données qui ne
tolèrent pas de pertes (encore que l'UDP entre le capteur et le serveur ne soit pas forcement adapté pour ca...
timestamper les données recues depuis les capteurs
lors d'une requette
'''
########################################################################################################################
class DataBuffer:
def __init__(self,nbinit):
self.mutex = Lock()
self.nb=nbinit;
self.dataBuffer=[]
self.nbdata=0
#initialisation avec des valeurs en "rampe" de 0 à 1
with self.mutex:
for ix in range(1, self.nb+ 1):
self.dataBuffer.append([ ix/self.nb])
def setData(self,i,val):
#print("tentative d'écriture à indice %s de la valeur %s" % (i , val))
if (i>=self.nb):
print("tentative d'écriture à indice %s trop grand" % (i))
return 0
else:
with self.mutex:
self.nbdata+=1
self.dataBuffer[i]=val
def getData(self,i):
if (i>=self.nb):
print("tentative de lecture à indice %s trop grand" % (i))
return 0
else:
with self.mutex:
return self.dataBuffer[i]
# question: est ce que c'est bien la valeur qui est copiée lors du return, et non pas une référence, auquel cas hors
# du mutex, la valeur référencée pourrait devenir incohérente
########################################################################################################################
#réception des données depuis les différents capteurs en UDP sur port 10000
#https://riptutorial.com/fr/python/example/4985/recevoir-des-donnees-via-udp
class CommSensor(Thread):
def __init__(self, sharedDataInit):
Thread.__init__(self)
self.sharedData=sharedDataInit;
self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
self.sock.bind(('', 10000)) # premier champ vide pour recevoir depuis n'importe quelle adresse,sinon IP en chaine de caractères
#self.sock.setblocking(0)
self.oldti=0
#self.displayIncommingFromSensor=False
self.displayIncommingFromSensor=True
def run(self):
while True:
#print('thread CommSensor ');
msg, addr = self.sock.recvfrom(8192) # This is the amount of bytes to read at maximum
if self.displayIncommingFromSensor:
print("Got message from %s: %s" % (addr, msg ))
change=1;
#pour un seul champ
# self.sharedData.dataBuffer[0]=int(msg)
# print("valeur recue: " + str(self.sharedData.dataBuffer[0]))
#pour plusieurs champs
ti=time.time()
chaine=str(self.sharedData.nbdata) + " valeurs recues: ";
chaine+=str(ti)+ " " +str(ti-self.oldti) + " "
listfields=msg.split()
if (len(listfields)>1):
# if False: #pour plus tard quand je gérerai l'identification des messages
if True:
adresseMAC=listfields[0]
chaine += " @MAC: "+ adresseMAC.decode('utf-8') + " "
try:
numero_data=int(listfields[1])
chaine += "num: " + str(numero_data) +" "
for i in range(0, len(listfields)-2):
# self.sharedData.dataBuffer[0+i]=int(listfields[i])
self.sharedData.setData(numero_data+i,float(listfields[i+2]))
chaine+=str(numero_data+i) + " -> " + str(self.sharedData.getData(numero_data+i)) + " , " ;
if self.displayIncommingFromSensor:
print(chaine)
except ValueError:
if self.displayIncommingFromSensor:
print("erreur parsing")
continue
self.oldti=ti
#TODO tuer ce thread lorsque la fenêtre principale ferme
########################################################################################################################
#chaque client voulant lire des données capteurs se connecte en TCP, ce qui crée une thread à chaque connexion
#https://riptutorial.com/fr/python/example/4985/recevoir-des-donnees-via-udp
class CommServer(Thread):
##########################################################""
def __init__(self, sharedDataInit):
Thread.__init__(self)
self.sharedData=sharedDataInit;
#self.displayIncommingFromClient=False
#self.displayResponseToClient=False
self.displayIncommingFromClient=True
self.displayResponseToClient=True
##########################################################""
def run(self):
print("New Thread server")
# http://sametmax.com/les-context-managers-et-le-mot-cle-with-en-python/
#utilisation du context manager pour libérer les ressources socket quand on quitte l'appli
#https://stackoverflow.com/questions/16772465/how-to-use-socket-in-python-as-a-context-manager
#https://hg.python.org/cpython/file/e57c8a90b2df/Lib/socket.py#l87
#oui la methode __exit__( de socket ferme bien la socket!
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
host = ""
port = 30000
s.bind((host, port)) # premier champ vide pour recevoir depuis n'importe quelle adresse,sinon IP en chaine de caractères
print("socket binded to port", port)
# put the socket into listening mode
s.listen(5)
print("socket is listening")
# a forever loop until client wants to exit
while True:
# establish connection with client
c, addr = s.accept()
# lock acquired by client
# print_lock.acquire()
print('Connected to :', addr[0], ':', addr[1])
# Start a new thread and return its identifier
_thread.start_new_thread(self.threaded, (c,))
#s.close()
##########################################################""
# thread fuction
def threaded(self,c):
while True:
# data received from client
data = c.recv(1024)
if self.displayIncommingFromClient:
print("receving " + str(data))
if not data:
print('Bye')
# lock released on exit
# print_lock.release()
break # sort du while -> déconnexion
# décodage de la requete: format r n1 n2...
listfields = data.split()
if self.displayIncommingFromClient:
print(str(listfields))
reponse =""
if listfields[0]==b'r':
for i in range(1, len(listfields)): #saute le premier champ
nbdatarequise=int(listfields[i])
reponse+= str(self.sharedData.getData(nbdatarequise)) + " ";
else:
print("probleme formatage requete")
# conn.sendall(data)
#reponse = str(self.sharedData.dataBuffer[0]) + chr(13) # + chr(10) : ne pas mettre le 10 sinon VAL3 interprete comme un caracatère débutant la chaine suiavnte...
reponse+= chr(13) # + chr(10) : ne pas mettre le 10 sinon VAL3 interprete comme un caracatère débutant la chaine suiavnte...
if self.displayResponseToClient:
print("sending " + str(reponse))
c.sendall(reponse.encode('utf-8'))
# connection closed
c.close()
''' s1, s2 = socket.socketpair()
b1 = bytearray(b'----')
b2 = bytearray(b'0123456789')
b3 = bytearray(b'--------------')
s2.recvmsg_into([b1, memoryview(b2)[2:9], b3])
(22, [], 0, None)
[b1, b2, b3]
'''
#time.sleep(1)
# TODO tuer tous ces thread thread lorsque la fenêtre principale ferme
# https://stackoverflow.com/questions/323972/is-there-any-way-to-kill-a-thread
# on ne doit pas tuer les threads à la bourrin (par contre possible avec process
# facon propre : https://dzone.com/articles/understanding
########################################################################################################################
if __name__ == '__main__':
try:
sharedData=DataBuffer(10000); #10000 données capteur différentes au max
thread_1 = CommSensor(sharedData);
thread_1.start()
thread_2 = CommServer(sharedData);
thread_2.start()
# Attend que les threads se terminent
#thread_1.join()
#thread_2.join()
while True:
time.sleep(1)
#print("...")
except KeyboardInterrupt:
#print("attente fin thread 1")
#thread_1.join()
print("bye")
#dans pyCharm, cliquer sur la tête de mort rouge pour bien tuer tout les processus et libérer les numeros de ports (envoi de SIGKILL)
#NE PAS SE CONNECTER AU WIFI ROBOT AIP SI J'UTILISE PC RAPID avec IP 1.49
#ajouter un mutex sur les données partagées
=====Application simulateur de client capteurs=====
#!/usr/bin/python3
#https://realpython.com/python-sockets/
import socket
HOST = '127.0.0.1' # The server's hostname or IP address
PORT = 30000 # The port used by the server
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.connect((HOST, PORT))
s.sendall(b'r 0 1 2')
data = s.recv(1024)
print('Received', repr(data))
=====Application simulateur de client capteurs en continu=====
#!/usr/bin/python3
import time # https://docs.python.org/fr/3/library/time.html
#https://realpython.com/python-sockets/
import socket
HOST = '127.0.0.1' # The server's hostname or IP address
PORT = 30000 # The port used by the server
########################################################################################################################
if __name__ == '__main__':
try:
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.connect((HOST, PORT))
while True:
s.sendall(b'r 1 2 3')
data = s.recv(1024)
# print('Received', repr(data))
print(repr(data))
time.sleep(0.01)
except KeyboardInterrupt:
print("bye")
=====Application simulateur de robot 6R staubli=====
#!/usr/bin/python3
# -*- coding: utf-8 -*
#Bertrand Vandeportaele 2019
import os
import sys
from PyQt4.QtGui import *
from PyQt4.QtNetwork import *
from PyQt4.QtCore import *
from PyQt4 import *
import re #pour découpage chaine comme sur https://stackoverflow.com/questions/2175080/sscanf-in-python
global numeroPremiereDonneeCapteur
#TODO: donner une valeur à cette variable en fonction de votre numéro d'étudiant
numeroPremiereDonneeCapteur=100
global etatBouton
etatBouton=0
global slider1Value
slider1Value=0
global slider2Value
slider2Value=0
global slider3Value
slider3Value=0
global slider4Value
slider4Value=0
global slider5Value
slider5Value=0
global slider6Value
slider6Value=0
global led0Button
################################################################################
def close():
print('close')
exit(0)
################################################################################
def commutTimer():
global timer
print('commutTimer')
if timer.isActive():
timer.stop()
commutTimerButton.setText('start stream sensor')
else:
timer.start()
commutTimerButton.setText('stop stream sensor')
################################################################################
def slider1ValueChanged( value ):
#label.setText( str( value )
global numeroPremiereDonneeCapteur
global labelSlider1Value
global slider1Value
slider1Value=value
#labelSlider1Value.setText( "J1: "+str(slider1Value) )
#https://mkaz.blog/code/python-string-format-cookbook/
labelSlider1Value.setText( str( numeroPremiereDonneeCapteur+0)+ " -> J1: {:6d}".format(slider1Value) )
print('changed')
################################################################################
def slider2ValueChanged( value ):
#label.setText( str( value )
global numeroPremiereDonneeCapteur
global labelSlider2Value
global slider2Value
slider2Value=value
labelSlider2Value.setText( str( numeroPremiereDonneeCapteur+1)+ " -> J2: {:6d}".format(slider2Value) )
print('changed')
################################################################################
def slider3ValueChanged( value ):
#label.setText( str( value )
global numeroPremiereDonneeCapteur
global labelSlider3Value
global slider3Value
slider3Value=value
labelSlider3Value.setText( str( numeroPremiereDonneeCapteur+2)+ " -> J3: {:6d}".format(slider3Value) )
print('changed')
################################################################################
def slider4ValueChanged( value ):
#label.setText( str( value )
global numeroPremiereDonneeCapteur
global labelSlider4Value
global slider4Value
slider4Value=value
labelSlider4Value.setText( str( numeroPremiereDonneeCapteur+3)+ " -> J4: {:6d}".format(slider4Value) )
print('changed')
################################################################################
def slider5ValueChanged( value ):
#label.setText( str( value )
global numeroPremiereDonneeCapteur
global labelSlider5Value
global slider5Value
slider5Value=value
labelSlider5Value.setText( str( numeroPremiereDonneeCapteur+4)+ " -> J5: {:6d}".format(slider5Value) )
print('changed')
################################################################################
def slider6ValueChanged( value ):
#label.setText( str( value )
global numeroPremiereDonneeCapteur
global labelSlider6Value
global slider6Value
slider6Value=value
labelSlider6Value.setText( str( numeroPremiereDonneeCapteur+5)+ " -> J6: {:6d}".format(slider6Value) )
print('changed')
################################################################################
def bouton0():
global numeroPremiereDonneeCapteur
global led0Button
global etatBouton
global labelButtonValue
etatBouton=(etatBouton+1)%2
if etatBouton==0:
led0Button.setText('Activer la sortie TOR')
else:
led0Button.setText('Desactiver la sortie TOR')
labelButtonValue.setText( str( numeroPremiereDonneeCapteur+6)+" : {:6d}".format(etatBouton) )
print('etatBouton: '+ str(etatBouton) +" \n");
# led0Button.setText('Appuyer sur le bouton')
# else:
# led0Button.setText('Relacher le bouton')
################################################################################
def sendUDP(i):
global numeroPremiereDonneeCapteur
global udpSocket
global destIP
global portOut
DestIP = QHostAddress(destIP);
global slider1Value
global slider2Value
global slider3Value
global slider4Value
global slider5Value
global slider6Value
global etatBouton
# chaine=str(slider1Value)+ " " + str(slider2Value)
#ajout @MAC bidon
# chaine="00:00:00:00:00:00 "+str(slider1Value)+ " " + str(slider2Value)
#ajout champs vides pour être compatible avec le joystick wifi
#@MAC: BC:DD:C2:FE:6F:F0 num: 0 0 -> 529.0 , 1 -> 534.0 , 2 -> 0.0 , 3 -> 0.0 , 4 -> 0.0 , 5 -> -73.0 , 6 -> 63.0 ,
chaine="00:00:00:00:00:00 "+str(numeroPremiereDonneeCapteur)+ " " +str(slider1Value)+ " " + str(slider2Value) + " " + str(slider3Value) + " " + str(slider4Value) + " " + str(slider5Value) + " " + str(slider6Value)+" " +str(etatBouton)
#chaines bidons pour générer erreur de parsing sur le serveur
# chaine="00:00:00:00:00:00 0 0 0 "+"687f"+" 0 0 "+str(slider1Value)+ " " + str(slider2Value)
chaine=chaine+chr(13)+chr(10)
print("la chaine envoyée est: "+chaine)
udpSocket.writeDatagram(chaine,DestIP, portOut);
################################################################################
def timerUpdate():
sendUDP(0)
################################################################################
global led0Button
#destIP='192.168.1.50' #pc simulateur
#destIP='192.168.0.112' #pc simulateur
#destIP='192.168.1.49' #pc serveur rapid connecté en filaire à réseau AIP
destIP='127.0.0.1' #pc serveur sur la boucle locale
portOut=10000
posx=10
posy=10
sizex=500
sizey=150
################################################################################
#par défaut: numeroPremiereDonneeCapteur= 100
#option -n pour choisir numeroPremiereDonneeCapteur
if len(sys.argv)==3:
if sys.argv[1]=='-n':
numeroPremiereDonneeCapteur= int(sys.argv[2])
print("réglage de numeroPremiereDonneeCapteur à: ",str(numeroPremiereDonneeCapteur));
app = QApplication(sys.argv)
w=QDialog()
statusLabel =QLabel('En attente de datagrammes UDP depuis le PIC32')
commutTimerButton=QPushButton('stop stream sensor')
quitButton = QPushButton('&Quit')
led0Button = QPushButton('Activer la sortie TOR')
udpSocket =QUdpSocket()
udpSocket.bind(portOut, QUdpSocket.ShareAddress)
app.connect(quitButton,QtCore.SIGNAL('clicked()'), close)
app.connect(commutTimerButton, QtCore.SIGNAL('clicked()'), commutTimer)
app.connect(led0Button,QtCore.SIGNAL('clicked()'), bouton0)
buttonLayout =QHBoxLayout()
buttonLayout.addStretch(1)
buttonLayout.addWidget(quitButton)
buttonLayout.addWidget(commutTimerButton)
buttonLayout.addStretch(1)
#button1Layout =QHBoxLayout()
#button1Layout.addStretch(1)
#button1Layout.addWidget(led0Button)
#button1Layout.addStretch(1)
global labelButtonValue
labelButtonValue=QLabel( )
labelButtonValue.setGeometry(250, 50, 50, 35)
#labelButtonValue.setText( "x: "+str(0 ) )
labelButtonValue.setText( str( numeroPremiereDonneeCapteur+6)+" : {:6d}".format(0) )
button1Layout =QHBoxLayout()
button1Layout.addStretch(1)
button1Layout.addWidget(labelButtonValue)
button1Layout.addStretch(1)
button1Layout.addWidget(led0Button)
button1Layout.addStretch(1)
#http://koor.fr/Python/CodeSamplesQt/PyQtSlider.wp
###################################
slider1 = QSlider(Qt.Horizontal);
slider1.setMinimum(-160)
slider1.setMaximum(160)
slider1.setGeometry( 10, 10, 600, 40 )
slider1.valueChanged.connect(slider1ValueChanged )
slider1.setValue( 0 )
global labelSlider1Value
labelSlider1Value=QLabel( )
labelSlider1Value.setGeometry(250, 50, 50, 35)
labelSlider1Value.setText( str( numeroPremiereDonneeCapteur+0)+ " -> J1: "+str(0 ) )
slider1Layout =QHBoxLayout()
slider1Layout.addWidget(labelSlider1Value)
slider1Layout.addWidget(slider1)
###################################
slider2 = QSlider(Qt.Horizontal);
slider2.setMinimum(-127.5)
slider2.setMaximum(127.5)
slider2.setGeometry( 10, 10, 600, 40 )
slider2.valueChanged.connect(slider2ValueChanged )
slider2.setValue( 0 )
global labelSlider2Value
labelSlider2Value=QLabel( )
labelSlider2Value.setGeometry(250, 50, 50, 35)
labelSlider2Value.setText( str( numeroPremiereDonneeCapteur+1)+ " -> J2: "+str(0 ) )
slider2Layout =QHBoxLayout()
slider2Layout.addWidget(labelSlider2Value)
slider2Layout.addWidget(slider2)
###################################
slider3 = QSlider(Qt.Horizontal);
slider3.setMinimum(-134.5)
slider3.setMaximum(134.5)
slider3.setGeometry( 10, 10, 600, 40 )
slider3.valueChanged.connect(slider3ValueChanged )
slider3.setValue( 0 )
global labelSlider3Value
labelSlider3Value=QLabel( )
labelSlider3Value.setGeometry(250, 50, 50, 35)
labelSlider3Value.setText( str( numeroPremiereDonneeCapteur+2)+ " -> J3: "+str(0 ) )
slider3Layout =QHBoxLayout()
slider3Layout.addWidget(labelSlider3Value)
slider3Layout.addWidget(slider3)
###################################
slider4 = QSlider(Qt.Horizontal);
slider4.setMinimum(-270)
slider4.setMaximum(270)
slider4.setGeometry( 10, 10, 600, 40 )
slider4.valueChanged.connect(slider4ValueChanged )
slider4.setValue( 0 )
global labelSlider4Value
labelSlider4Value=QLabel( )
labelSlider4Value.setGeometry(250, 50, 50, 35)
labelSlider4Value.setText( str( numeroPremiereDonneeCapteur+3)+ " -> J4: "+str(0 ) )
slider4Layout =QHBoxLayout()
slider4Layout.addWidget(labelSlider4Value)
slider4Layout.addWidget(slider4)
###################################
slider5 = QSlider(Qt.Horizontal);
slider5.setMinimum(-109.5)
slider5.setMaximum(+120.5)
slider5.setGeometry( 10, 10, 600, 40 )
slider5.valueChanged.connect(slider5ValueChanged )
slider5.setValue( 0 )
global labelSlider5Value
labelSlider5Value=QLabel( )
labelSlider5Value.setGeometry(250, 50, 50, 35)
labelSlider5Value.setText( str( numeroPremiereDonneeCapteur+4)+ " -> J5: "+str(0 ) )
slider5Layout =QHBoxLayout()
slider5Layout.addWidget(labelSlider5Value)
slider5Layout.addWidget(slider5)
###################################
slider6 = QSlider(Qt.Horizontal);
slider6.setMinimum(-270)
slider6.setMaximum(270)
slider6.setGeometry( 10, 10, 600, 40 )
slider6.valueChanged.connect(slider6ValueChanged )
slider6.setValue( 0 )
global labelSlider6Value
labelSlider6Value=QLabel( )
labelSlider6Value.setGeometry(250, 50, 50, 35)
labelSlider6Value.setText( str( numeroPremiereDonneeCapteur+5)+ " -> J6: "+str(0 ) )
slider6Layout =QHBoxLayout()
slider6Layout.addWidget(labelSlider6Value)
slider6Layout.addWidget(slider6)
###################################
sliderLayout =QVBoxLayout()
sliderLayout.addStretch(1)
sliderLayout.addLayout(slider1Layout)
sliderLayout.addStretch(1)
sliderLayout.addLayout(slider2Layout)
sliderLayout.addStretch(1)
sliderLayout.addLayout(slider3Layout)
sliderLayout.addStretch(1)
sliderLayout.addLayout(slider4Layout)
sliderLayout.addStretch(1)
sliderLayout.addLayout(slider5Layout)
sliderLayout.addStretch(1)
sliderLayout.addLayout(slider6Layout)
sliderLayout.addStretch(1)
mainLayout = QVBoxLayout()
mainLayout.addLayout(buttonLayout)
mainLayout.addLayout(sliderLayout)
mainLayout.addLayout(button1Layout)
mainLayout.addWidget(statusLabel)
w.setLayout(mainLayout)
chaine='@BVDP2021: Port Em '+str(portOut) +' vers IP: '+str(destIP)
w.setWindowTitle(chaine)
#timer adapted from example 1 of https://www.programcreek.com/python/example/52106/PyQt4.QtCore.QTimer
timer = QtCore.QTimer()
app.connect(timer, QtCore.SIGNAL('timeout()'), timerUpdate)
timer.setInterval(100)
timer.start()
w.setGeometry(posx,posy,sizex,sizey)
#donne le focus au bouton 1
led0Button.setDefault(True)
w.show()
app.exec_()
=====Application affichage animé de données capteurs=====
#!/usr/bin/python3
#trouvé sur https://stackoverflow.com/questions/48389470/python-update-matplotlib-from-threads
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
import numpy as np
import threading
import random
import time
import socket
HOST = '127.0.0.1' # The server's hostname or IP address
PORT = 30000 # The port used by the server
class MyDataClass():
def __init__(self):
self.XData = [0]
self.YData = [0]
#self.Y2Data = [0]
class MyPlotClass():
def __init__(self, dataClass):
self._dataClass = dataClass
self.hLine, = plt.plot(0, 0)
self.ani = FuncAnimation(plt.gcf(), self.run, interval = 30, repeat=True) #30 ms entre affichage
def run(self, i):
print("plotting data")
self.hLine.set_data(self._dataClass.XData, self._dataClass.YData)
self.hLine.axes.relim()
self.hLine.axes.autoscale_view()
class MyDataFetchClass(threading.Thread):
def __init__(self, dataClass):
threading.Thread.__init__(self)
self._dataClass = dataClass
self._period = 0.1 #durée d'attente entre lecture sur socket
self._nextCall = time.time()
# with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as self.s:
#todo gérer probleme de connexion
self.s= socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.s.connect((HOST, PORT))
def run(self):
# while True:
# print("updating data")
# # add data to data class
# self._dataClass.XData.append(self._dataClass.XData[-1] + 1)
# self._dataClass.YData.append(random.randint(0, 256))
# # sleep until next execution
# self._nextCall = self._nextCall + self._period;
# time.sleep(self._nextCall - time.time())
while True:
print("updating data")
modeYT=True
if modeYT:
self.s.sendall(b'r 1 2 3')
else:
s.sendall(b'r 6 7 3')
data = self.s.recv(1024)
# print('Received', repr(data))
print(repr(data))
ti = time.time()
listfields = data.split()
if modeYT:
self._dataClass.XData.append(self._dataClass.XData[-1] + 1)
self._dataClass.YData.append(float(listfields[0]))
# sleep until next execution
self._nextCall = self._nextCall + self._period;
time.sleep(self._nextCall - time.time())
#x.append(i)
#y.append(float(listfields[0]))
#y2.append(float(listfields[1]))
#
# else:
# x.append(float(listfields[0]))
# y.append(float(listfields[1]))
#if ((float)(listfields[2])==1.0): # bouton pressé, on efface
#x.clear()
#y.clear()
# il faudrait effacer la figure
# i+=1
# y.append(psutil.cpu_percent())
# ax.plot(x,y,color='b')
# if modeYT:
# ax.plot(x, y2, color='r')
# ax.set_xlim(left=max(0,i-50),right=i+50)
# fig.canvas.draw()
# time.sleep(0.01)
# except KeyboardInterrupt:
# print("bye")
data = MyDataClass()
plotter = MyPlotClass(data)
fetcher = MyDataFetchClass(data)
fetcher.start()
plt.show()
#fetcher.join()
=====Programme ESP8266 pour capteur=====
Un même programme pour différents capteurs, le choix du comportement du programme se fait à l'aide de macro dans le programme pour (des)activer certaines fonctionnalités.
//B. Vandeportaele 2019
//choisir la carte NodeMCU1.0(ESP12E module)
//pour uploader, presser le bouton reset quand l'ide arduino affiche "connecting..." puis relacher
//régler les macros suivantes pour régler le comportement de la carte:
//#define HX711PRESENT
#define JOYPRESENT
#include
#include
#include
WiFiUDP Client;
#include
#define WSout D2
#define PIXELCOUNT 2
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(PIXELCOUNT, WSout, NEO_GRB + NEO_KHZ800);
// A UDP instance to let us send and receive packets over UDP
WiFiUDP udp;
// wifi connection variables
unsigned int localPort = 10000; // local port to listen for UDP packets
#include "listereseauxwifi.h"
//const char* ssid = "78BF39";
//const char* password = "6D842DAE4B";
char *MACADDRESS=NULL;
#define TRANSMITOVERWIFI
#ifdef TRANSMITOVERWIFI
//String ip = "192.168.1.49"; // the remote IP address
IPAddress Ip;
#endif
// /home/bvandepo/.arduino15/packages/esp8266/hardware/esp8266/2.3.0-rc2/libraries/ESP8266WiFi/src/ESP8266WiFi.h
// /home/bvandepo/.arduino15/packages/esp8266/hardware/esp8266/2.3.0-rc2/cores/esp8266/IPAddress.h
//////////////////////////
//i2c
//#include
//attention le code de la balance est bloquant, et donc si le module HX711 n'est pas présent mais que le code est executé, l'esp8266 va faire un watchdog reset et ceci apparait sur la console série:
// esp8266 ets Jan 8 2013,rst cause:2, boot mode:(3,7)
/*
The codes are :
0 -> normal startup by power on
1 -> hardware watch dog reset
2 -> software watch dog reset (From an exception)
3 -> software watch dog reset system_restart (Possibly unfed watchdog got angry)
4 -> soft restart (Possibly with a restart command)
5 -> wake up from deep-sleep
Looking at the provided code you can decide from what reason the chip is restarting.
*/
#ifdef HX711PRESENT
#include "HX711.h"
HX711 scale(D4, D3); // DOUT, SCK
#endif
#ifdef JOYPRESENT
//////////////////////////////////////////
class JoystickESP8266CD4053B {
//L'entrée analogique est forcément A0, car c'est la seule
private:
int16_t minX, maxX, minY, maxY;
float xFactor, yFactor;
int16_t centerX, centerY, dZ;
uint8_t pinSelect, pinB;
int16_t iX, iY; //position intégrée
int16_t b; //bouton 1=pressé
int16_t X, Y; //position lue
int16_t dX, dY; //différence de position par rapport au Zero
public:
JoystickESP8266CD4053B(uint8_t pinSelectinit, uint8_t pinBinit, int16_t dZinit) {
pinSelect = pinSelectinit;
pinB = pinBinit;
dZ = dZinit; //dead Zone
//par défaut les limites pour x et y sont les valeurs min et max codable
minX = -32768;
maxX = 32767;
minY = -32768;
maxY = 32767;
xFactor = 1;
yFactor = 1;
}
void init() { //analogRead ne fonctionne pas avant appel de setup()
pinMode(pinSelect, OUTPUT);
pinMode(pinB, INPUT_PULLUP); //pull up pour bouton
iX = 0;
iY = 0;
digitalWrite(pinSelect, LOW);
delayMicroseconds(3);
centerX = analogRead(A0);
digitalWrite(pinSelect, HIGH);
delayMicroseconds(3);
centerY = analogRead(A0);
b = !digitalRead(pinB);
}
void setLimits(int16_t minXinit, int16_t maxXinit, int16_t minYinit, int16_t maxYinit) {
minX = minXinit;
maxX = maxXinit;
minY = minYinit;
maxY = maxYinit;
}
void setPos(int16_t xinit, int16_t yinit) {
iX = xinit;
iY = yinit;
}
void setPosCenter() {
iX = (maxX + minX) / 2;
iY = (maxY + minY) / 2;
}
void setFactorOrientation(float xFactorInit, float yFactorInit) {
xFactor = xFactorInit;
yFactor = yFactorInit;
}
void update() {
digitalWrite(pinSelect, LOW);
delayMicroseconds(3);
X = analogRead(A0);
digitalWrite(pinSelect, HIGH);
delayMicroseconds(3);
Y = analogRead(A0);
dX = (X - centerX) * xFactor;
dY = (Y - centerY) * yFactor;
/*if (abs(dX)>dZ)
x=x+dX;
if (abs(dY)>dZ)
y=y+dY;
*/
if (dX > dZ)
if (iX < maxX - dX)
iX = iX + dX;
else
iX = maxX;
if (dX < -dZ)
if (iX > minX - dX)
iX = iX + dX;
else
iX = minX;
if (dY > dZ)
if (iY < maxY - dY)
iY = iY + dY;
else
iY = maxY;
if (dY < -dZ)
if (iY > minY - dY)
iY = iY + dY;
else
iY = minY;
b = !digitalRead(pinB);
/* Serial.print("centerX: ");
Serial.print(centerX);
Serial.print("centerY: ");
Serial.println(centerY);
Serial.print("dX: ");
Serial.print(dX);
Serial.print("dY: ");
Serial.println(dY);
*/
}
int16_t getdX() {
return dX;
}
int16_t getdY() {
return dY;
}
int16_t getiX() {
return iX;
}
int16_t getiY() {
return iY;
}
int16_t getX() {
return X;
}
int16_t getY() {
return Y;
}
int16_t getB() {
return b;
}
bool isUp() {
return (Y > centerY + dZ);
}
bool isDown() {
return (Y < centerY - dZ);
}
bool isLeft() {
return (X > centerX + dZ);
}
bool isRight() {
return (X < centerY - dZ);
}
};
//////////////////////////////////////////
JoystickESP8266CD4053B joy(D3, D4, 3);
#endif
//////////////////////////////////////////
void Debug(char * msg)
{
#if 1
Serial.print(msg);
#endif
}
//////////////////////////////////////////
unsigned long computeDeltaTime(unsigned long time_begin) {
unsigned long time_current;
unsigned long time_delta;
time_current = micros();
if (time_current > time_begin)
time_delta = time_current - time_begin;
else //in case micros has rolled over 2^32, may happen approx. once each hour (3600000000us)
time_delta = time_current - (time_begin - (unsigned long )4294967296);
return time_delta;
}
//////////////////////////////////////////
#ifdef TRANSMITOVERWIFI
void sendMessage(byte message[]) {
//sprintf((char*)message,"Hello ca va la?");
udp.beginPacket(Ip, 10000);
udp.write(message, strlen((char*)message));
udp.endPacket();
}
#endif
//////////////////////////////////////////
int getMessage(byte message[], int maxByte) {
int cb = udp.parsePacket();
if (cb == 0) return 0; //no dataavailable, quit
if (cb > maxByte) cb = maxByte; //don't overrun the buffer, the remaining part of the message WILL BE LOST!!
// We've received a packet, read the data from it
udp.read(message, cb); // read the packet into the buffer
message[cb] = 0; //add a 0 after the content in the buffer
return cb;
}
//////////////////////////////////////////
#define BUFFER_RX_MAX 50
#define ERROR -1
#define NOTHING 0
#define STARTING 5
#define WAITINGFORCONNECTION 6
#define CONNECTED 7
class Communication {
public:
int state; //last message received
byte message[BUFFER_RX_MAX + 1]; //+1 to add an additional 0 after the received bytes to ensure that the string is correctly finished, even if the sender sent some errors
int numeroReseauWifi;
int nbRetryConnectWifi;
////////////
Communication() {
state = STARTING;
numeroReseauWifi=0;
nbRetryConnectWifi=0;
configListeReseauWifi();
}
////////////
void loop() {
//doc at https://www.arduino.cc/en/Reference/WiFiStatus
if (state == STARTING) {
//Wifi Configuration
Serial.println ( "Wifi Configuration" );
#ifdef TRANSMITOVERWIFI
Ip.fromString(listeReseauWifi[numeroReseauWifi].serverIP);
#endif
//WiFi.begin ( ssid, password );
WiFi.begin ( listeReseauWifi[numeroReseauWifi].ssid, listeReseauWifi[numeroReseauWifi].password );
//stocke l'adresse mac
if (MACADDRESS==NULL){
MACADDRESS=strdup(WiFi.macAddress().c_str());
Serial.print ( "MAC address for this board: " );
Serial.println ( MACADDRESS);
}
// Wait for connection
state = WAITINGFORCONNECTION;
} else if (state == WAITINGFORCONNECTION) {
if ( WiFi.status() != WL_CONNECTED ) {
Serial.print ( "WAITINGFORCONNECTION to " );
Serial.print ( numeroReseauWifi);
Serial.print ( " ");
Serial.println ( listeReseauWifi[numeroReseauWifi].ssid);
nbRetryConnectWifi++;
//flash bleu
pixels.setPixelColor(0, Color(0,0,255));
pixels.show();
delay(100);
pixels.setPixelColor(0, Color(0,0,0));
pixels.show();
delay(100);
#define MAX_NB_RETRY_CONNECT_WIFI 50
if (nbRetryConnectWifi>MAX_NB_RETRY_CONNECT_WIFI)
{
nbRetryConnectWifi=0;
numeroReseauWifi=(numeroReseauWifi+1)%NbReseauWifi;
WiFi.begin ( listeReseauWifi[numeroReseauWifi].ssid, listeReseauWifi[numeroReseauWifi].password );
Ip.fromString(listeReseauWifi[numeroReseauWifi].serverIP);
//Serial.print ( "Now trying to connect to " );
//flash rouge
pixels.setPixelColor(0, Color(255,0,0));
pixels.show();
delay(100);
pixels.setPixelColor(0, Color(0,0,0));
pixels.show();
delay(100);
}
} else {
state = CONNECTED;
//flash vert
pixels.setPixelColor(0, Color(0,255,0));
pixels.show();
delay(500);
pixels.setPixelColor(0, Color(0,0,0));
pixels.show();
delay(500);
}
} else if (state == CONNECTED) {
Serial.println ( "" );
Serial.print ( "Connected to " );
Serial.println (listeReseauWifi[numeroReseauWifi].ssid );
Serial.print ( "Local IP address: " );
Serial.println ( WiFi.localIP() );
Serial.print ( "Server IP address: " );
Serial.println (listeReseauWifi[numeroReseauWifi].serverIP );
Serial.println("Starting UDP socket");
udp.begin(localPort);
Serial.print("Local port: ");
Serial.println(udp.localPort());
state = NOTHING;
}
else {
if ( WiFi.status() == WL_CONNECTION_LOST) {
Serial.print ( "WL_CONNECTION_LOST\n" );
state = STARTING;
} else if ( WiFi.status() == WL_DISCONNECTED) {
Serial.print ( "WL_DISCONNECTED\n" );
state = STARTING;
} else {
int n = getMessage(message, BUFFER_RX_MAX);
if (n == 0)
Debug(".");
else {
Debug("packet received, length=");
char msg[11];
snprintf(msg, 10, "%d", n);
Debug(msg);
Debug(", content= ");
Debug((char*)message);
/* if (strcmp((char*)message,"OpenTheDoorCompletelyPlease")==0){
state=OPENTHEDOOR;
Debug(" -> Open The Door\n");
}
else if (strcmp((char*)message,"CloseTheDoorCompletelyPlease")==0){
state=CLOSETHEDOOR;
Debug(" -> Close The Door\n");
}
else if (strcmp((char*)message,"StopTheDoor")==0){
state=STOPTHEDOOR;
Debug(" -> StopTheDoor\n");
}
else if (strcmp((char*)message,"SwitchTheLight")==0){
state=SWITCHTHELIGHT;
Debug(" -> SwitchTheLight\n");
}
else{
state=ERROR;
Debug(" -> Error\n");
}*/
}
}
}
}
//////////////////////////
void EmitMessage() {
#ifdef TRANSMITOVERWIFI
/*
static int counter=0;
static int b1state=0;
static int b2state=0;
static int b3state=0;
//simulate random presses/releases of buttons
if(random(0, 20)==0) b1state=(b1state+1)%2;
if(random(0, 15)==0) b2state=(b2state+1)%2;
if(random(0, 25)==0) b3state=(b3state+1)%2;
*/
if (state == NOTHING) {
/* counter++;
sprintf((char*)message,"compteur= %6d b1:%d b2:%d b3:%d\n",counter,b1state,b2state,b3state);
*/
/*digitalWrite(D2,LOW);
delay(3000);
digitalWrite(D2,HIGH);
delay(3000);
*/
//sprintf((char*)message, "%d %d %d\n", Ax - AxZero, Ay - AyZero, Sw);
unsigned short int numero_data=0; //identification si le capteur fournit plusieurs messages
#ifdef HX711PRESENT
static float poidsmax=20000;
float poids= scale.get_units(1); // scale.get_units(); // inversion!!!!
if (abs(poids)>poidsmax)
poidsmax=abs(poids);
//Serial.println(poids, 1);
unsigned char R=0;
unsigned char G=0;
unsigned char B=0;
if (poids>0)
R=poids*255./poidsmax;
else if (poids<0)
G=-poids*255./poidsmax;
//else tout à 0
pixels.setPixelColor(0, Color(R,G,B));
pixels.show();
numero_data=0; //identification si le capteur fournit plusieurs messages
//sprintf((char*)message, "%s %d %f %d %d\n",MACADDRESS, numero_data,poids,R,G);
sprintf((char*)message, "%s %d %f\n",MACADDRESS, numero_data,poids);
sendMessage(message);
#endif
#ifdef JOYPRESENT
//joystick
joy.update();
pixels.setPixelColor(0, Color(joy.getX()/ 8, joy.getY() / 8, 0)); //attention Ax,Ay va de 0 à 1024 inclus
pixels.setPixelColor(1, Color(0, 0, joy.getB() * 128)); //attention Ax,Ay va de 0 à 1024 inclus
pixels.show();
numero_data=1; //identification si le capteur fournit plusieurs messages
sprintf((char*)message, "%s %d %d %d %d %d %d %d %d\n", MACADDRESS, numero_data, joy.getX() , joy.getY(),joy.getB(), joy.getdX(),joy.getdY(),joy.getiX(),joy.getiY());
sendMessage(message);
#endif
/*
//compteur
numero_data=1; //identification si le capteur fournit plusieurs messages
static int cpt=0;
cpt++;
sprintf((char*)message, "%s %d %d\n", MACADDRESS, numero_data, cpt);
sendMessage(message);
*/
//sprintf((char*)message,"%d\n",analogRead(A0));
}
#endif
}
};
//////////////////////////////////////////
Communication communication;
//////////////////////////////////////////
//Be carefull, The Watchdog resets every 4 seconds if the loop function is not finished
//////////////////////////////////////////
uint32_t Color(byte r, byte g, byte b) {
uint32_t c;
c = r;
c <<= 8;
c |= g;
c <<= 8;
c |= b;
return c;
}
//////////////////////////////////////////
void setup() {
randomSeed(analogRead(0));
//serial communication setup for debugging
Serial.begin ( 115200 );
delay(100);
Serial.println ( "Serial Configuration Completed" );
Serial.println( "Compiled: " __DATE__ ", " __TIME__ ", " __VERSION__);
//GPIOs Configuration
Serial.println ( "GPIOs Configuration (some already done through constructors)" );
//Wifi Configuration done in first iterations of communication.loop
#ifdef HX711PRESENT
// scale.set_scale(250.f); //// this value is obtained by calibrating the scale with known weights
scale.tare(10); //tare basée sur moyenne de 10 mesures
#endif
#ifdef JOYPRESENT
joy.init();
joy.setLimits(-32767, 32767, -32767, 32767);
joy.setPosCenter();
joy.setFactorOrientation(0.1, 0.1);
#endif
pixels.begin();
for (byte i = 0; i < PIXELCOUNT; i++)
pixels.setPixelColor(i, Color(0, 0, 0));
pixels.show();
};
//////////////////////////////////////////
// the loop function runs over and over again forever
void loop() {
//Serial.println(micros());
//test_buttons_and_relays();
communication.loop();
communication.EmitMessage();
// if (communication.isSwitchTheLight()) light.commute();
if (communication.state!=CONNECTED)
delay(100); //for debuging purposes, it slows the display
delay(2);
}
//////////////////////////////////////////
fichier header à mettre dans le dossier du sketch pour paramétrer les différents hotspot wifi auxquels la carte va essayer de se connecter:
//B. Vandeportaele 2019
#define NB_RESEAU_WIFI_MAX 50
////////////////////////////////////////////
typedef struct
{
const char* ssid;
const char* password;
const char* serverIP;
} reseauWifi;
reseauWifi listeReseauWifi[NB_RESEAU_WIFI_MAX];
//variable globale pour gérer la liste de réseau
unsigned char NbReseauWifi=0;
////////////////////////////////////////////
void ajouteReseauWifi(char * ssid, char * clef, char* serverIP){
if (NbReseauWifi