2012-09-05 20:01:37 +02: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 22:00:20 +02:00
void sendNTPpacket () {
2012-09-05 20:01:37 +02: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
// you can send a packet requesting a timestamp:
2012-09-08 22:00:20 +02:00
Udp . beginPacket ( timeserver , 123 ); //NTP requests are to port 123
2012-09-05 20:01:37 +02:00
Udp . write ( packetBuffer , NTP_PACKET_SIZE );
Udp . endPacket ();
Serial . println ( "Sending ntp packet" );
delay ( 1000 );
if ( Udp . parsePacket () ) {
// 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 ]);
unsigned long lowWord = word ( packetBuffer [ 42 ], packetBuffer [ 43 ]);
// combine the four bytes (two words) into a long integer
// this is NTP time (seconds since Jan 1 1900):
unsigned long secsSince1900 = highWord << 16 | lowWord ;
// Unix time starts on Jan 1 1970. In seconds, that's 2208988800:
const unsigned long seventyYears = 2208988800UL ;
// subtract seventy years:
unsigned long epoch = secsSince1900 - seventyYears + TIMEZONE ;
Serial . println ( "Adjusting time" );
chronodot . adjust ( DateTime ( epoch ));
}
}
void setup () {
Serial . begin ( 9600 );
2012-09-08 22:00:20 +02:00
pinMode ( 5 , OUTPUT );
SPI . begin ();
2012-09-05 20:01:37 +02: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)
Udp . begin ( 8888 );
2012-09-08 22:00:20 +02:00
sendNTPpacket ();
2012-09-05 20:01:37 +02:00
}
void loop () {
webserver . processConnection ();
delay ( 500 );
}