2012-09-05 18:01:37 +00:00
# include <Wire.h>
# include <SPI.h>
# include <Ethernet.h>
# include "WebServer.h"
# include "BMP085.h"
# include "DHT.h"
# include "TSL2561.h"
# include "Chronodot.h"
# define TIMEZONE 7200 // 2 hours
# define DHTPIN 2
# define DHTTYPE DHT22
# define PREFIX ""
# define NTP_PACKET_SIZE 48
static uint8_t mac [ ] = { 0xDE , 0xAD , 0xBE , 0xEF , 0xFE , 0xED } ;
static IPAddress ip = IPAddress ( 192 , 168 , 1 , 210 ) ;
static IPAddress timeserver = IPAddress ( 192 , 43 , 244 , 18 ) ;
P ( indexHtml ) = " <!DOCTYPE html><html><head><meta charset='utf-8' /><title>Station Météo</title> "
" <style>html, body{background: #000;color: #fff;}body{font-family: 'DejaVu Sans', Verdana, Arial, sans-serif;font-size: 100%;margin: 0;padding: 0;}#home{background: #000;color: #fff;margin: 1em;padding: 0;}#home h1{color: #f7c000;font-size: 2em;margin: 1em;text-align: center;}#home p{background: #111;border: 1px solid #444;font-size: 1.5em;list-style-type: none;padding: 0;width: 100%;text-align: center;}#home table{background: #111;border: 1px solid #444;font-size: 1.5em;list-style-type: none;padding: 0;width: 100%;text-align: center;}#home ul#links li{font-weight: bold;margin: 0;padding: 0.8em;text-align: center;}#footer{background: #000;color: #888;font-size: 0.8em;margin: 1em;text-align: center;padding: 0;}</style> "
" </head><body> "
" <div id='home'><h1>Station Météo</h1> "
" <table><tr><th>Temps</th><th>T [°C]</th><th>P [Pa]</th><th>Alt [m]</th><th>Hr [%]</th><th>Lx [lux]</th></tr> "
" <tr><td>0</td><td>0</td><td>0</td><td>0</td><td>0</td><td>0</td></tr></table> "
" <p><label>Intervale de mise à jour (en secondes) : </label><input id='interval' type='number' value=2 /></p></div><div id='footer'>par Nathanal Restori</div> "
" <script>function updateInfo(){var xhr=new XMLHttpRequest();xhr.open('GET', '/sensors.json');xhr.onreadystatechange=function(){if (xhr.readyState==4 && xhr.status==200){var response=JSON.parse(xhr.responseText);var rows=document.getElementsByTagName('tr');var cell=rows[1].firstChild;var index=0;while (cell){cell.firstChild.nodeValue=response.sensors[index].data;cell=cell.nextSibling;index++;}}};xhr.send(null);}updateInfo();var updateID=setInterval(updateInfo, 2000);var interval=document.getElementById('interval');interval.addEventListener('change', function(e){clearInterval(updateID);updateID=setInterval(updateInfo, e.target.value*1000);}, true);</script> "
" </body></html> " ;
// no-cost stream operator as described at
// http://sundial.org/arduino/?page_id=119
template < class T >
inline Print & operator < < ( Print & obj , T arg )
{ obj . print ( arg ) ; return obj ; }
BMP085 bmp ;
DHT dht ( DHTPIN , DHTTYPE ) ;
TSL2561 tsl ( TSL2561_ADDR_FLOAT ) ;
Chronodot chronodot ;
WebServer webserver ( PREFIX , 80 ) ;
byte packetBuffer [ NTP_PACKET_SIZE ] ;
EthernetUDP Udp ;
void defaultCmd ( WebServer & server , WebServer : : ConnectionType type , char * url_tail , bool tail_complete ) {
server . httpSuccess ( ) ;
server . printP ( indexHtml ) ;
}
void sensorsJsonCmd ( WebServer & server , WebServer : : ConnectionType type , char * url_tail , bool tail_complete ) {
float temperature = bmp . readTemperature ( ) ;
int32_t pressure = bmp . readPressure ( ) ;
float altitude = bmp . readAltitude ( ) ;
float humidity = dht . readHumidity ( ) ;
uint32_t lum = tsl . getFullLuminosity ( ) ;
uint16_t lightIr = lum > > 16 ;
uint16_t lightFull = lum & 0xFFFF ;
DateTime time = chronodot . now ( ) ;
server . httpSuccess ( " application/json " ) ;
server < < " { \" sensors \" : [ "
< < " { \" data \" : \" " < < time . hour ( ) < < " : " < < time . minute ( ) < < " : " < < time . second ( ) < < " " < < time . day ( ) < < " / " < < time . month ( ) < < " / " < < time . year ( ) < < " \" }, "
< < " { \" data \" : " < < temperature < < " }, "
< < " { \" data \" : " < < pressure < < " }, "
< < " { \" data \" : " < < altitude < < " }, "
< < " { \" data \" : " < < humidity < < " }, "
< < " { \" data \" : " < < tsl . calculateLux ( lightFull , lightIr ) < < " } "
< < " ] } " ;
}
2012-09-08 20:00:20 +00:00
void sendNTPpacket ( ) {
2012-09-05 18:01:37 +00:00
// set all bytes in the buffer to 0
memset ( packetBuffer , 0 , NTP_PACKET_SIZE ) ;
// Initialize values needed to form NTP request
// (see URL above for details on the packets)
packetBuffer [ 0 ] = 0 b11100011 ; // LI, Version, Mode
packetBuffer [ 1 ] = 0 ; // Stratum, or type of clock
packetBuffer [ 2 ] = 6 ; // Polling Interval
packetBuffer [ 3 ] = 0xEC ; // Peer Clock Precision
// 8 bytes of zero for Root Delay & Root Dispersion
packetBuffer [ 12 ] = 49 ;
packetBuffer [ 13 ] = 0x4E ;
packetBuffer [ 14 ] = 49 ;
packetBuffer [ 15 ] = 52 ;
// all NTP fields have been given values, now
2012-09-10 15:07:09 +00:00
// you can send a packet requesting a timestamp:
2012-09-08 20:00:20 +00:00
Udp . beginPacket ( timeserver , 123 ) ; //NTP requests are to port 123
2012-09-05 18:01:37 +00:00
Udp . write ( packetBuffer , NTP_PACKET_SIZE ) ;
Udp . endPacket ( ) ;
Serial . println ( " Sending ntp packet " ) ;
2012-09-10 15:07:09 +00:00
delay ( 1000 ) ;
if ( Udp . parsePacket ( ) ) {
2012-09-05 18:01:37 +00:00
// We've received a packet, read the data from it
Udp . read ( packetBuffer , NTP_PACKET_SIZE ) ; // read the packet into the buffer
//the timestamp starts at byte 40 of the received packet and is four bytes,
// or two words, long. First, esxtract the two words:
unsigned long highWord = word ( packetBuffer [ 40 ] , packetBuffer [ 41 ] ) ;
2012-09-10 15:07:09 +00:00
unsigned long lowWord = word ( packetBuffer [ 42 ] , packetBuffer [ 43 ] ) ;
2012-09-05 18:01:37 +00:00
// combine the four bytes (two words) into a long integer
// this is NTP time (seconds since Jan 1 1900):
2012-09-10 15:07:09 +00:00
unsigned long secsSince1900 = highWord < < 16 | lowWord ;
2012-09-05 18:01:37 +00:00
// Unix time starts on Jan 1 1970. In seconds, that's 2208988800:
2012-09-10 15:07:09 +00:00
const unsigned long seventyYears = 2208988800UL ;
2012-09-05 18:01:37 +00:00
// subtract seventy years:
unsigned long epoch = secsSince1900 - seventyYears + TIMEZONE ;
2012-09-10 15:07:09 +00:00
2012-09-05 18:01:37 +00:00
Serial . println ( " Adjusting time " ) ;
chronodot . adjust ( DateTime ( epoch ) ) ;
}
}
void setup ( ) {
Serial . begin ( 9600 ) ;
2012-09-08 20:00:20 +00:00
pinMode ( 5 , OUTPUT ) ;
SPI . begin ( ) ;
2012-09-05 18:01:37 +00:00
//----- Ethernet/WebServer
Serial . println ( " INIT Ethernet " ) ;
Ethernet . begin ( mac , ip ) ;
webserver . begin ( ) ;
webserver . setDefaultCommand ( & defaultCmd ) ;
webserver . addCommand ( " sensors.json " , & sensorsJsonCmd ) ;
//----- Sensors
Serial . println ( " INIT Sensors " ) ;
bmp . begin ( ) ;
dht . begin ( ) ;
tsl . begin ( ) ;
chronodot . begin ( ) ;
// You can change the gain on the fly, to adapt to brighter/dimmer light situations
//tsl.setGain(TSL2561_GAIN_0X); // set no gain (for bright situtations)
tsl . setGain ( TSL2561_GAIN_16X ) ; // set 16x gain (for dim situations)
// Changing the integration time gives you a longer time over which to sense light
// longer timelines are slower, but are good in very low light situtations!
tsl . setTiming ( TSL2561_INTEGRATIONTIME_13MS ) ; // shortest integration time (bright light)
//tsl.setTiming(TSL2561_INTEGRATIONTIME_101MS); // medium integration time (medium light)
//tsl.setTiming(TSL2561_INTEGRATIONTIME_402MS); // longest integration time (dim light)
2012-09-10 15:07:09 +00:00
2012-09-05 18:01:37 +00:00
Udp . begin ( 8888 ) ;
2012-09-08 20:00:20 +00:00
sendNTPpacket ( ) ;
2012-09-05 18:01:37 +00:00
}
void loop ( ) {
webserver . processConnection ( ) ;
delay ( 500 ) ;
}