Affichage temperature sur page web

Bonsoir,

Je m'excuse si ce post n' a pas sa place ici car ca concerne Arduino mais aussi le reste sur RPI et page web, les modérateurs peuvent le supprimer si c'est le cas mais j' aurais vraiment besoin de votre aide.

J' explique en quoi ca consiste.

Je suis loin d' etre un pro en developpement, mais peut etre qu' eventuellement des gens du forum plus competents que nous aurons une idee.

Je suis sur aussi que c' est juste un detail a pauffiner mais je n' ai pas les connaissances assez pointues pour determiner ce qui cloche.

Voila c'est assez simple dans l' abolu je voudrais afficher sur une page web les données des sondes de temperature en temps reel installées dans une serre.

La partie technique fonctionne tres bien, sans trop entrer dans les details techniques les capteurs sont sur une carte Arduino qui envoie les informations de la sonde toutes les secondes sur le Raspberry par bus I2C, sur le Raspberry j'ai un script Python qui recoit les infos du bus I2C qui les met un peu en forme, ce meme script lance un serveur websocket, j' utilise Tornado sous Raspbian Linux sur le RPI, il envoie les données recues de l' arduino sur le port 8888 du localhost du RPI environ chaque seconde aussi.

Sur ce meme RPI j' ai un serveur web lighttpd, un equivalent du serveur Apache, et un script HTML qui ecoute sur le port 8888 du websocket et ensuite affiche la temperature sur une page web sous forme de jauge en javascript ca fait tres joli :slight_smile:

J' ai aussi une adresse ip fixe je suis inscrit chez no-ip.com et j' arrive a afficher la page de mon serveur web parfaitement jusque la ca marche.
Le probleme c'est que ca marche en local, mais pas quand j'essaye d' afficher ma page en passant par une connection internet exterieure !

L' adresse est http://celticrpi.no-ip.org/test-tornado

En local quand je tape cette adresse tout fonctionne la jauge affiche la temperature en continu et est raffraichie chaque seconde par le websocket mais quand je passe par internet exterieur ca affiche la page mais pas la jauge et ca dit que je suis deconnecté du websocket.

Sur mon routeur j' ai bien fait les redirections de port 80,443 et 8888 du RPI sur le port local correspondant ca c'est ok aussi.

Donc ca marche chez moi mais par exemple si je demande a une copine de regarder mon adresse de chez elle la jauge ne s affiche pas et le websocket est down.

Ca m' enerve :slight_smile:

Hier j' ai essayé de me connecter a mon RPI avec cette adresse a travers un serveur proxy anonyme, pour simuler une connection exterieure, la ca fonctionne sauf que sur les proxy anonyme je dois decocher une case "remove script" pour que ca marche, si je laisse la fonction "remove script" du proxy activee ca ne marche pas, ce qui signifie que l'execution du script qui affiche ma jauge en .js est bloquée sur les navigateurs?

la j' avoue que je ne saisis pas ou ca coince :wink:

Toute aide serais la bienvenue, mais comme je l' ai dit je suis presque sur que c'est tout bete a resoudre, mais je ne sais pas comment le faire :slight_smile:

Voila,

Merci pour votre aide :slight_smile:

Fabrice

PS: je publie les sources au besoin mais il y a de l' IDE Arduino, du Python et du HTML :wink:

Bonsoir

Quand j'accède à ton URL, j'ai bien la page HTML qui me dit "Status: disonnected!"

Et quand j'affiche le source de la page, je vois du javascript, qui s'exécute donc sur mon ordi dans mon navigateur.
Et dans ce javascript une ligne qui me semble louche :   var ws = new WebSocket("ws://yanapi:8888/ws");

A part ça, ce serait bien d'ajouter un c à "Status: disonnected!" :grin:

Bonsoir bricoleau, merci pour ton test :slight_smile:

Oui c'est ca mon probleme, ca marche nickel sur reseau local meme en tapant l' adresse no-ip dans un navigateur, mais ca ne marche pas en passant par internet exterieur.

Je n' etais pas sur non plus de var ws ...
je viens de le remplacer par ws://celticrpi.no-ip.org/ws et ca marche pareil en local mais sur le net je ne sais pas ...

je corrige le C :slight_smile:

Bonsoir,

Tu as peut-être corrigé le problème, en tout cas de mon côté ça fonctionne.
Joli travail.

Voici le code python pour I2C et websocket

#!/usr/bin/env python
import tornado.httpserver
import tornado.websocket
import tornado.ioloop
import tornado.web
import os
import sys
import smbus
import time
import struct
# for RPI version 1, use "bus = smbus.SMBus(0)"
bus = smbus.SMBus(1)

# This is the address we setup in the Arduino Program
address = 0x04

wss =[]
class WSHandler(tornado.websocket.WebSocketHandler):
  def check_origin(self, origin):
 return True
  def open(self):
    print 'New user is connected.\n' 
    if self not in wss:
      wss.append(self)
  def on_close(self):
    print 'connection closed\n'
    if self in wss:
      wss.remove(self)

application = tornado.web.Application([(r'/ws', WSHandler),])

if __name__ == "__main__":
  os.system('modprobe w1-gpio')
  #os.system('modprobe w1-therm')
  interval_msec = 2000
  
  def get_data():
 return bus.read_i2c_block_data(address, 0);

  def get_float(data, index):
 bytes = data[4*index:(index+1)*4]
 return struct.unpack('f', "".join(map(chr, bytes)))[0]

  def wsSend(message):
    for ws in wss:
      if not ws.ws_connection.stream.socket:
        print "Web socket does not exist anymore!!!"
        wss.remove(ws)
      else:
        ws.write_message(message)

  def read_temp():
    try:
 data = get_data()
 temp = get_float(data, 0)
 #print '%.2f' % temp
 #print(get_float(data, 1))
 #print "--------"   
 temp = ('%.2f' % get_float(data, 0))
 #read temp. onboard sensor    
 file = open('/sys/class/thermal/thermal_zone0/temp','r')
 lines = file.readlines()
 #tempcpu = ('%.2f' % float(lines[0])/1000)
 temp += ';' + str(float(lines[0])/1000)
 #temp += ';' + str(tempcpu)
 file.close()
 #print temp
 wsSend(temp)
    except:
 wsSend("-;-")

  http_server = tornado.httpserver.HTTPServer(application)
  http_server.listen(8888)
    
  main_loop = tornado.ioloop.IOLoop.instance()
  sched_temp = tornado.ioloop.PeriodicCallback(read_temp, interval_msec,   io_loop = main_loop)

  sched_temp.start()
  main_loop.start()

Bonsoir 3sigma, euh serieux ca fonctionne ?

Sérieux ça fonctionne.

Essaie, si tu as la possibilité, de te connecter à Internet par un autre moyen que par ta box, pour tester.
Ca m'est déjà arrivé, dans la même configuration que toi, d'avoir le même genre de problème quand j'étais connecté à Internet via le même routeur que celui sur lequel j'avais fait les redirections de port.

Ah ben flute :slight_smile: tu vois les jauges bouger en temps réel ?

Oui, promis juré:

Status: Connection active!

Temperature sonde CTN: 23.79 C
Temperature CPU RPI: 39.007 C

Et voici le code HTML qui recoit le web socket sur le port 8888 et affiche les jauges de température:

<!doctype html>
<html>
<head>
<title>Capteur de temperature de mon salon</title>
<meta http-equiv="Content-Type" content="text/javascript; charset=UTF-8" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.2/jquery.min.js"></script>
<script type="text/javascript" src="./libraries/RGraph.common.core.js" ></script>
<script type="text/javascript" src="./libraries/RGraph.thermometer.js" ></script>
<script type="text/javascript" src="./libraries/RGraph.gauge.js" ></script>
<script type="text/javascript" src="./libraries/RGraph.common.effects.js" ></script>
<script type='text/javascript'>

  $(window).load(function () {
    var ws = new WebSocket("ws://celticrpi.no-ip.org:8888/ws");

    ws.onopen = function(evt) {
      var conn_status = document.getElementById('conn_text');
      conn_status.innerHTML = "Status: Connection active!"
    };
                
    ws.onmessage = function(evt) {
      var ds18b20_reading = document.getElementById('ds18b20_temp');
      var cpu_reading = document.getElementById('cpu_temp');
      current_temp = (evt.data).split(";");			
      ds18b20_reading.innerHTML = "Temperature sonde CTN: " + current_temp[0] + " C";                        
      cpu_reading.innerHTML = "Temperature CPU RPI: " + current_temp[1]+ " C";
      drawGraph_environment();
      drawGraph_CPU();
                 
    };

    ws.onclose = function(evt) {
      var conn_status = document.getElementById('conn_text');
      conn_status.innerHTML = "Status: disconnected!"
    };
  });

  function drawGraph_environment(){
    var canvas = document.getElementById('cvs_E');
    RGraph.Clear(canvas);

    var thermometer = new RGraph.Gauge('cvs_E', 0,50,     eval(current_temp[0]))     	
    .set('title.top', 'Sonde CTN')
    .set('value.text', true)
    .set('value.text.y.pos', 0.3)
    .set('value.text.units.post',' C')
    .draw();
  }
 	
  function drawGraph_CPU(){
    var canvas = document.getElementById('cvs_CPU');
    RGraph.Clear(canvas);

    var thermometer = new RGraph.Thermometer('cvs_CPU', 0,100,     eval(current_temp[1]))
    .set('title.side', 'RPi CPU')
    .set('value.label', false)
    .set('scale.visible', true)
    .set('scale.decimals',2)
    .set('gutter.left', 80)
    .set('gutter.right', 40)
    .draw();
  }
	
</script>
</head>
<body>
<h2>Capteur de temperature CTN sur Arduino vers Raspberry par bus I2C</h2>
<label id="conn_text"></label>



<label id="ds18b20_temp">DS18B20: </label>

<label id="cpu_temp">CPU temp: </label>





<canvas id="cvs_E" width="300" height="300">[No canvas support]</canvas>
<canvas id="cvs_CPU" width="150" height="200">[No canvas support]</canvas>
</body>
</html>

3sigma ca affiche seulement en texte ou tu vois aussi les jauges graphiques?

Oui j' aimerais essayer mais je n' ai pas encore d' autre acces internet ni de 3g, je vais demander a un voisin :slight_smile:

Et pour finir le code Arduino pour lire la sonde CTN 10 Kohms récupéree sur une machine à laver :slight_smile: et qui l' envoie sur le bus I2C:

Si ca peut aider quelqu'un pour un projet c'est avec plaisir.

#include <Wire.h>

#define SLAVE_ADDRESS 0x04

#define FLOATS_SENT 2

// which analog pin to connect
#define THERMISTORPIN 0         
// resistance at 25 degrees C
#define THERMISTORNOMINAL 4940      
// temp. for nominal resistance (almost always 25 C)
#define TEMPERATURENOMINAL 24   
// how many samples to take and average, more takes longer
// but is more 'smooth'
#define NUMSAMPLES 5
// The beta coefficient of the thermistor (usually 3000-4000)
#define BCOEFFICIENT 3950
// the value of the 'other' resistor
#define SERIESRESISTOR 10000    
float temperature = 0.00;
float luminosity = 0.00;
float data[FLOATS_SENT];
 
int samples[NUMSAMPLES];
int ledPin = 9; 
const float threshold = 29.50; 
 
void setup(void) {
  Serial.begin(9600);
  analogReference(EXTERNAL);
     analogWrite(ledPin, 0); 
  // initialize i2c as slave
  Wire.begin(SLAVE_ADDRESS);
  // define callbacks for i2c communication
  Wire.onRequest(sendData);
}
 
void loop(void) {
  uint8_t i;
  float average;
   analogWrite(ledPin, 0); 
  // take N samples in a row, with a slight delay
  for (i=0; i< NUMSAMPLES; i++) {
   samples[i] = analogRead(THERMISTORPIN);
   delay(10);
  }
 
  // average all the samples out
  average = 0;
  for (i=0; i< NUMSAMPLES; i++) {
     average += samples[i];
     
  }
  average /= NUMSAMPLES;
 
  Serial.print("Average analog reading "); 
  Serial.println(average);
 
  // convert the value to resistance
  average = 1023 / average - 1;
  average = SERIESRESISTOR / average;
  Serial.print("Thermistor resistance "); 
  Serial.println(average);
 
  float steinhart;
  steinhart = average / THERMISTORNOMINAL;     // (R/Ro)
  steinhart = log(steinhart);                  // ln(R/Ro)
  steinhart /= BCOEFFICIENT;                   // 1/B * ln(R/Ro)
  steinhart += 1.0 / (TEMPERATURENOMINAL + 273.15); // + (1/To)
  steinhart = 1.0 / steinhart;                 // Invert
  steinhart -= 273.15;                         // convert to C
  data[0] = steinhart;
  data[1] = threshold;
  
  if (steinhart >= threshold) {
    for (int fadeValue = 180 ; fadeValue <= 255; fadeValue += 5) {
    // sets the value (range from 0 to 255):
    analogWrite(ledPin, fadeValue);
    
    // wait for 30 milliseconds to see the dimming effect
    //delay(30);
  }
  }
  else {
    for (int fadeValue = fadeValue - 10 ; fadeValue >= 0; fadeValue -= 5) {
    // sets the value (range from 0 to 255):
    
    analogWrite(ledPin, fadeValue);
    //analogWrite(ledPin, HIGH);
    //analogWrite(ledPin, LOW);
    // wait for 30 milliseconds to see the dimming effect
    //delay(30);
    }
  }
  Serial.print("Treshold ");
  Serial.println(threshold);
  Serial.print("Temperature "); 
   Serial.print(steinhart);
  Serial.println(" *C");
 
  delay(1000);
}
void sendData(){
  Wire.write((byte*) &data[0], FLOATS_SENT*sizeof(float));
}

Pour info le partie qui commence par : if (steinhart >= threshold) { ............. jusque delay(1000) est une petite modif perso qui permet de controler par PWM la vitesse d' un moteur DC 4 fils récupéré sur une alim PC, il s' enclenche quand la temperature atteint un threshold ce qui permet de ventiler la sonde et faire redescendre la temperature autour, ce ne sert a concretement a rien dans l' affichage web de la sonde mais c'etait un essai en combinant 2 projet l' un étant le controle du moteur DC par PWM et l' autre étant l' acquisition de temperature d' une sonde CTN par le formule de steinhart et pour finir de rendre tout ca visible sur le web par le bus I2C entre l' Arduino et le RPI.

Il y a quelques fautes de denomination par exemple ledpin est la pin PWM qui commande le moteur, pas une LED.
Il y a aussi quelques lignes en commentaires qui sont a adapter.

Est-il possible de transferer ce post dans les projets résolus pour peut etre aider d' autres personnes?

Merci encore à bricoleau et 3sigma :slight_smile:

Fabrice

Bonsoir pepe, etant sur raspberry j' ai un peu cherché et opté finalement pour Tornado.

Au niveau des jauges ca passe par jquery et des jauges .js de chez RGRAPH qui sont plutot sympas.

TU pourrais m' indiquer une methode plus ancienne pour remplacer le websocket?

Surtout que j' aimerais garder le temps reel, on peut bien sur passer par une DB mysql pour enregistrer les donnees et relire la DB pour les afficher mais ca je teste plus tard

Tu as sans doute arrêté ton système ce matin, mais chez moi tout fonctionnait hier, y compris les jauges.

Je ne suis pas d'accord avec pepe sur les Websockets: c'est une technologie très bien supportée par les navigateurs modernes et le fait que la jauge ne fonctionne que sur certains systèmes vient sans doute d'un problème de compatibilité de la jauge, pas des Websockets.
Et il faudrait savoir tout d'abord d'où vient ton problème de communication avant d'incriminer les Websockets.

Personnellement, je t'encourage vivement à utiliser les Websockets plutôt qu'une techno plus ancienne et moins efficace.

bonjour,
les websokets ne sont pas en cause.
c'est surtout le format html qui l'est sur certains navigateurs qui ne se sont pas encore mis de concert.
et encore plus avec le html5.

<canvas id="cvs_E" width="300" height="300">[No canvas support]</canvas>
<canvas id="cvs_CPU" width="150" height="200">[No canvas support]</canvas>

c'est canvas qui peut être mal interprété par les navigateurs et ne rien afficher.
le mieux serait de debugger le JS pour voir ce qui bloque.