#!/usr/bin/python # -*- coding: utf-8 -*- # exemple pyDuino - par X. HINAULT - www.mon-club-elec.fr # Juillet 2013 - Tous droits réservés - GPLv3 # voir : https://github.com/sensor56/pyDuino # Serveur TCP générant une page HTML + Javascript affichant un graphique avec la librairie dygraphs. from pyduino import * # importe les fonctions Arduino pour Python import numpy as np # tableaux de valeurs numeriques import datetime # pour operations facilitees sur date/heure # entete declarative ipLocale=Ethernet.localIP() # auto - utilise l'ip de l'interface eth0 du systeme #ipLocale='192.168.1.25' # manuel - attention : utiliser la meme IP qu'une interface reseau du systeme # pour connaitre les interfaces reseau sur le systeme : utiliser la commande $ ifconfig print ipLocale # affiche l'adresse IP port=8080 # attention port doit etre au dessus de 1024 sinon permission refusee par securite - 8080 pour http serverHTTP=EthernetServer(ipLocale, port) # crée un objet serveur utilisant le port 8080 = port HTTP > 1024 #--- setup --- def setup(): global serverHTTP, ipLocale, port #serverHTTP.begin(10) # initialise le serveur - fixe nombre max connexion voulu serverHTTP.begin() # initialise le serveur - nombre max connexion par defaut = 5 print ("Serveur TCP actif avec ip : " + ipLocale + " sur port : " + str(port) ) #--- fin setup # -- loop -- def loop(): global serverHTTP print ("Attente nouvelle connexion entrante...") clientDistant, ipDistante = serverHTTP.clientAvailable() # attend client entrant # code bloque ici tant que pas client ! Si present, on recupere d'un coup objet client ET son ip print "Client distant connecte avec ip :"+str(ipDistante) # affiche IP du client #--- requete client --- requete=serverHTTP.readDataFrom(clientDistant) # lit les donnees en provenance client d'un coup print requete # affiche requete recue #--- reponse serveur --- reponse=( # ( ... ) pour permettre multiligne.. httpResponse() # entete http OK 200 automatique fournie par la librairie Pyduino # contenu page - ici date / heure du serveur et mesure nalogique A2 + pageHTML() # voir la fonction separee - pour clarte du code +"\n") # fin reponse serverHTTP.writeDataTo(clientDistant, reponse) # envoie donnees vers client d'un coup print "Reponse envoyee au client distant : " #print (bytes(reponse)) #print (reponse) # affiche la reponse envoyee - debug #serverHTTP.close() # remarque : le socket = serveur doit rester ouvert # quand on quitte l'application: la connexion TCP reste active un peu donc erreur si re-execution trop rapide du code # on peut utiliser un port voisin dans ce cas... delay(10) # entre 2 loop() # -- fin loop -- #--- fonction fournissant la page HTML --- def pageHTML(): # code Python a executer avant envoyer page # donnees types dataGraph="" # utiliser options plutot que premiere ligne #dataGraph=( #""" #"Date,Temperature\\n" + #""") # donnees sous forme d'une chaine # format "x,y\n" """ for i in range(1000): # format "x,y\n" dataGraph=dataGraph+"\""+str(i)+","+str(i)+"\\n \" +" + "\n" # le 2eme \n est dans la page HTML, le premier dans la chaine des donnees dataGraph=dataGraph+"\""+str(i)+","+str(i)+"\\n \"" + "\n" # derniere ligne sans le plus """ # attention : le plus est dans la chaine # donnees sous forme d'un tableau # [ [1,10,100], [2,20,80], [3,50,60], [4,70,80] ] # dans ce cas, utiliser l'option labels obligatoirement #dataGraph=dataGraph+"[ [1,10,100], [2,20,80], [3,50,60], [4,70,80] ]" # ici, 1440 valeurs representant 1 mesure par minute pendant 24H nombreSeries=6 # nombre serie de donnees - attention definir autant de label y que de series data=np.zeros((1440,nombreSeries+1)) # tableau de 1000 lignes x 2 colonnes data[:,0] = np.arange(0,1440,1) # remplissage 1ere colonne = les x #data[:,1] = np.arange(0,1000,1) # remplissage 2eme colonne = les y for serie in range(1,nombreSeries+1): # defile serie des y de 1 à n data[:,serie] = (serie*5)+np.random.normal(0,1,size=1440) # remplissage 2eme colonne = les y1 #dataStr=",".join(data ) # pour convertir list en str avec elements separes par , #dataStr=str(data.tolist()) # convertit tableau numpy pour affichage dygraph ++ # formatage des x au format horaire et envoi data format texte refTime=datetime.datetime(int(year()), int(month()), int(day())) # date a utiliser - heure 00:00:00 si pas precise for t in range(1440-1) : # defile 1440-1 ères minutes theoriques dataTime=refTime+datetime.timedelta(0, t*60) # jours, secondes - ici toutes les minutes #dataTime=datetime.timedelta(0, t*60) # jours, secondes - ici toutes les minutes - sans refTime #print dataTime # format de donnees utilise : JJ/MM/YYYY hh:mm:ss , val \n #dataLine=today('/') + " " + hh +":"+mm + ":" + str(t)+","+dataValue+"\n" dataLine=str(dataTime)+","# format datetime JJ-MM-AAAA hh:mm:ss for serie in range(1,nombreSeries+1): # defile serie des y de 1 à n if serie==nombreSeries: dataLine=dataLine+str(data[t,serie]) # sans la virgule else : dataLine=dataLine+str(data[t,serie])+"," # sinon avec la virgule dataGraph=dataGraph+"\""+dataLine+"\\n \" +"+"\n" # format texte dans code JS # pas le 2eme \n si on veut source page compact... = "illisible" cote client # derniere ligne dataTime=refTime+datetime.timedelta(0, 1440*60) # jours, secondes - ici toutes les minutes dataLine=str(dataTime)+","# format datetime JJ-MM-AAAA hh:mm:ss for serie in range(1,nombreSeries+1): # defile serie des y de 1 à n if serie==nombreSeries: dataLine=dataLine+str(data[-1,serie]) # sans la virgule else : dataLine=dataLine+str(data[-1,serie])+"," # sinon avec la virgule dataGraph=dataGraph+"\""+dataLine+"\\n \" "+"\n" # format texte dans code JS #print dataGraph # debug # options du graphique Dygraph a utiliser optionsGraph=""" labels: [ "x", "y1=" , "y2=" , "y3=" , "y4=" , "y5=" , "y6="], // labels series width : 800, // largeur height: 600, // hauteur showRangeSelector: true // affiche l'outil de selection plage voulue """ # Attention, pas de , pour la derniere ligne ! pageHTML=( # debut page HTML """ Test Dygraphs

Test de graphique Dygraphs : affichage 1440 valeurs de données (tableau numpy) soit 1 valeur par minute pendant 24H """ ) # fin page HTML return pageHTML # la fonction renvoie la page HTML #--- obligatoire pour lancement du code -- if __name__=="__main__": # pour rendre le code executable setup() # appelle la fonction setup while not noLoop: loop() # appelle fonction loop sans fin