I've been interested in augmenting my network with Ethernet and WiFi devices for some time. So, just messing around with an Uno and an Ethernet Shield, I built a device that can (without the RF integration)
-
Control any Vera device through HTTP Commands
-
Can be controlled by VERA luup or any wget style command
-
be a sensor on my network
-
be an independant/agnostic layer with equal footing with My Sensors
-
be dependable
I'm not all the way there yet, but i built a sensor that can talk to my Vera, controlling vera devices and can be controlled by vera.
This is the web page it creates:
this sketch allow you to turn on/off a relay via a webpage or Vera, and control a vera device.
take a look:
ArduinoEthernetNode – 01:29
— Jim B
#include <Wire.h>
#include <EEPROM.h>
#include <SPI.h>
#include <Ethernet.h>
#include <EthernetUdp.h>
#include <utility/w5100.h>
#include <Time.h>
#include <Timezone.h>
#include <LiquidCrystal_I2C.h>
#include "DHT.h"
//#define DEBUG_ON
#define LED_PIN 8
#define DHT_SENSOR_PIN 7
#ifdef DEBUG_ON
#define DEBUG_PRINT(x) Serial.print(x)
#define DEBUG_PRINTLN(x) Serial.println(x)
#define SERIAL_START(x) Serial.begin(x)
#else
#define DEBUG_PRINT(x)
#define DEBUG_PRINTLN(x)
#define SERIAL_START(x)
#endif
//
boolean lightOn;
DHT dht;
//
LiquidCrystal_I2C lcd(0x27, 16, 2);
uint8_t clock[8] = {0x0,0xe,0x15,0x17,0x11,0xe,0x0}; // I'm-fetching-time-indicator for LCD display
//
EthernetUDP Udp;
EthernetServer server(80);
uint8_t mac[] = { 0xDE, 0xDE, 0xDE, 0xDE, 0xDE, 0xDE };
unsigned int localPort = 8888;
IPAddress timeServer(132, 163, 4, 101); // time-a.timefreq.bldrdoc.gov NTP server // IPAddress timeServer(132, 163, 4, 102); // time-b.timefreq.bldrdoc.gov NTP server // IPAddress timeServer(132, 163, 4, 103); // time-c.timefreq.bldrdoc.gov NTP server
const int NTP_PACKET_SIZE = 48; // NTP time stamp is in the first 48 bytes of the message
byte packetBuffer[ NTP_PACKET_SIZE]; //buffer to hold incoming and outgoing packets
byte socketStat[MAX_SOCK_NUM];
//
char myString[100];
byte locator = 0;
EthernetClient client;
const byte myserver[] = { 192,168,1,59 };
//
const char *dayOfWeek[] = {"Null","Sunday ","Monday ", "Tuesday ", "Wednesday ", "Thursday ", "Friday ", "Saturday "};
const char *monthString[] = {"NULL", "January", "February", "March", "April", "May", "June", "July", "August","September", "October", "November", "December"};
//
TimeChangeRule usEDT = {"EDT", Second, Sun, Mar, 2, -240}; //Eastern Daylight Time = UTC - 4 hours
TimeChangeRule usEST = {"EST", First, Sun, Nov, 2, -300}; //Eastern Standard Time = UTC - 5 hours
Timezone usET(usEDT, usEST);
TimeChangeRule *tcr;
boolean forceClockUpdate = true;
//
void setup()
{
SERIAL_START(9600);
lightOn = EEPROM.read(0);
pinMode(LED_PIN, OUTPUT);
dht.setup(DHT_SENSOR_PIN);
digitalWrite(LED_PIN, lightOn);
//
DEBUG_PRINTLN(F("configuring ethernet"));
if (Ethernet.begin(mac) == 0) // start Ethernet and UDP
{
DEBUG_PRINTLN(F("Failed to configure Ethernet using DHCP"));
while(true){}
}
server.begin();
Udp.begin(localPort);
//
lcd.init();
lcd.clear();
lightOn? lcd.backlight() : lcd.noBacklight();
lcd.createChar(0, clock);
}
//
void loop()
{
updateLCD();
getNTPtime();
webControl();
}
//
void updateLCD()
{
static int lastSecond;
time_t rightNow = now();
if (second(rightNow) != lastSecond)
{
lcd.setCursor(0,0);
lcd.print(F("Time:"));
DEBUG_PRINT(F("Time:"));
lcd.print(hourFormat12(rightNow) < 10 ? F(" ") : F(""));
DEBUG_PRINT(hourFormat12(rightNow) < 10 ? F(" ") : F(""));
lcd.print(hourFormat12(rightNow));
DEBUG_PRINT(hourFormat12(rightNow));
lcd.print(minute(rightNow) < 10 ? F(":0") : F(":"));
DEBUG_PRINT(minute(rightNow) < 10 ? F(":0") : F(":"));
lcd.print(minute(rightNow));
DEBUG_PRINT(minute(rightNow));
lcd.print(second(rightNow) < 10 ? F(":0") : F(":"));
DEBUG_PRINT(second(rightNow) < 10 ? F(":0") : F(":"));
lcd.print(second(rightNow));
DEBUG_PRINT(second(rightNow));
lcd.print(isAM() ? "am" : "pm");
DEBUG_PRINT(isAM() ? " am " : " pm ");
lcd.setCursor(0,1);
lcd.print(dayOfWeek[weekday(rightNow)]);
DEBUG_PRINTLN(dayOfWeek[weekday(rightNow)]);
lcd.print(F(" "));
lcd.setCursor(11,1);
lcd.print(month(rightNow) < 10 ? F(" ") : F(""));
lcd.print(month(rightNow));
lcd.print(day(rightNow) < 10 ? F("/0") : F("/"));
lcd.print(day(rightNow));
}
lastSecond = second(rightNow);
}
//unsigned long
void sendNTPpacket(IPAddress& address) // Send an NTP request to the time server at the given address
{
memset(packetBuffer, 0, NTP_PACKET_SIZE);
packetBuffer[0] = 0b11100011; // LI, Version, Mode
packetBuffer[1] = 0; // Stratum, or type of clock
packetBuffer[2] = 6; // Polling Interval
packetBuffer[3] = 0xEC; // Peer Clock Precision
packetBuffer[12] = 49;
packetBuffer[13] = 0x4E;
packetBuffer[14] = 49;
packetBuffer[15] = 52;
Udp.beginPacket(address, 123); //NTP requests are to port 123
Udp.write(packetBuffer,NTP_PACKET_SIZE);
Udp.endPacket();
}
//
void receiveTime(unsigned long newTime)
{
DEBUG_PRINT(F("Time value received: "));
int lastSecond = second();
int lastMinute = minute();
int lastHour = hour();
setTime(newTime);
if ((second() != lastSecond) || (minute() != lastMinute) || (hour() != lastHour))
{
DEBUG_PRINTLN(F("Clock updated...."));
DEBUG_PRINT(F("Sensor's time currently set to:"));
DEBUG_PRINT(hourFormat12() < 10? F(" 0") : F(" "));
DEBUG_PRINT(hourFormat12());
DEBUG_PRINT(minute() < 10? F(":0") : F(":"));
DEBUG_PRINT(minute());
DEBUG_PRINTLN(isAM()? F("am") : F("pm"));
DEBUG_PRINT(month());
DEBUG_PRINT(F("/"));
DEBUG_PRINT(day());
DEBUG_PRINT(F("/"));
DEBUG_PRINTLN(year());
DEBUG_PRINTLN(dayOfWeek[weekday()]);
}
lcd.setCursor(15,0);
lcd.print(F(" "));
}
//
void getNTPtime()
{
static unsigned long lastUpdateTime;
const unsigned long interval = 60000UL;
if ((millis() - lastUpdateTime >= interval) || forceClockUpdate)
{
lcd.setCursor(15,0);
lcd.write(0);
sendNTPpacket(timeServer); // send an NTP packet to a time server
delay(1000);
if (Udp.parsePacket())
{
Udp.read(packetBuffer,NTP_PACKET_SIZE); // read the packet into the buffer
unsigned long highWord = word(packetBuffer[40], packetBuffer[41]);
unsigned long lowWord = word(packetBuffer[42], packetBuffer[43]);
unsigned long secsSince1900 = highWord << 16 | lowWord;
DEBUG_PRINT(F("Seconds since Jan 1 1900 = "));
DEBUG_PRINTLN(secsSince1900);
DEBUG_PRINT(F("Unix time = "));
time_t utcEpoch = secsSince1900 - 2208988800UL;//seventyYears = 2208988800UL
DEBUG_PRINTLN(utcEpoch);
receiveTime(usET.toLocal(utcEpoch, &tcr) + 2); //about 2 seconds to call for time
}
if (!forceClockUpdate)
{
lastUpdateTime += interval;
}
forceClockUpdate = false;
}
}
//
void webControl()
{
EthernetClient client = server.available();
if (client)
{
while (client.connected())
{
if (client.available())
{
char c = client.read();
if (locator < 100)
{
myString[locator] = c;
locator++;
myString[locator] = '\0';
}
if (c == '\n') //if HTTP request has ended
{
DEBUG_PRINTLN(F("MyString ="));
DEBUG_PRINTLN(myString);
client.println(F("HTTP/1.1 200 OK")); //new page
client.println(F("Content-Type: text/html"));
client.println();
client.println(F("<HTML>"));
client.println(F("<HEAD>"));
client.println(F("<meta name='apple-mobile-web-app-capable' content='yes' />"));
client.println(F("<meta name='apple-mobile-web-app-status-bar-style' content='black-translucent' />"));
client.println(F("<link rel='stylesheet' type='text/css' href='http://homeautocss.net84.net/a.css' />"));
client.println(F("<TITLE>Jim's Home Automation</TITLE>"));
client.println(F("</HEAD>"));
client.println(F("<BODY>"));
client.println(F("<H1>NTP Clock/Light</H1>"));
client.println(F("<hr />"));
client.println(F("<br />"));
client.println(F("<a href=\"/?ledOn\"\">Light On</a>"));
client.println(F("<a href=\"/?ledOff\"\">Light Off</a><br />"));
client.println(F("<br />"));
client.println(F("<br />"));
client.println(F("<a href=\"/?phoneyOn\"\">PhoneyTV On</a>"));
client.println(F("<a href=\"/?phoneyOff\"\">PhoneyTV Off</a><br />"));
client.println(F("<br />"));
client.println(F("<br />"));
client.println(F("<a href=\"/?syncClock\"\">Force Synchronize Clock</a>"));
client.println(F("<br />"));
client.println(F("<br />"));
client.println(F("<hr />"));
client.println(F("<H2>Current Conditions</H2>"));
client.println(F("<H3>"));
client.println(dayOfWeek[weekday()]);
client.println(F(","));
client.println(monthString[month()]);
client.println(F(" "));
client.println(day());
client.println(F(","));
client.println(year());
client.println(F("<br />"));
client.println(F("<br />"));
client.println(F("<font color=\"blue\">Temperature</font>"));
client.println(F("<font color=\"red\">"));
client.println((int)floor(dht.toFahrenheit(dht.getTemperature()) + 0.5), 1);
client.println(F("</font>"));
client.println(F("<font color=\"blue\">F</font>"));
client.println(F("<br />"));
client.println(F("<H3><font color=\"blue\">Humidity</font>"));
client.println(F("<font color=\"red\">"));
client.println((int)floor(dht.getHumidity() + 0.5), 1);
client.println(F("</font>"));
client.println(F("<font color=\"blue\">%</font>"));
client.println(F("<br />"));
client.println(F("<div style=\"background-color:grey;"));
client.print(F(" color:black; margin:20px; padding:20px;\">"));
client.println(F("<h3>Jim Brower</h3>"));
client.println(F("<p>"));
client.println("©");
client.println(F(" 2014"));
client.println(F("</p>"));
client.println(F("</div>"));
client.println(F("</BODY>"));
client.println(F("</HTML>"));
delay(1);
client.stop();
if(strstr(myString, "?ledOn")) // control arduino pin and LCD backlight //checks for 'on'
{
lightOn = true;
EEPROM.write(0,0xFF);
digitalWrite(LED_PIN, HIGH);
lcd.backlight();
DEBUG_PRINTLN(F("Led On"));
}
if(strstr(myString, "?ledOff")) // compliment to above
{
lightOn = false;
EEPROM.write(0,0x00);
digitalWrite(LED_PIN, LOW);
lcd.noBacklight();
DEBUG_PRINTLN(F("Led Off"));
}
else if (strstr(myString, "?syncClock"))
{
forceClockUpdate = true;
DEBUG_PRINTLN(F("Sync Set"));
}
else if (strstr(myString, "?phoneyOn"))
{
phoneyTV(true);
DEBUG_PRINTLN(F("PhoneyTV On"));
}
else if (strstr(myString, "?phoneyOff"))
{
phoneyTV(false);
DEBUG_PRINTLN(F("PhoneyTV Off"));
}
myString[0] = '\0'; //clearing string for next read
locator = 0;
}
}
}
}
}
//
void phoneyTV(boolean status)
{
ShowSockStatus();
if (client.connect(myserver, 3480)) //starts client connection, checks for connection
{
DEBUG_PRINTLN(F("connected"));
client.print(F("GET /data_request?"));
client.print(F("id=action&output_format=xml"));
client.print(F("&DeviceNum=88"));
client.print(F("&serviceId=urn:upnp-org:"));
client.print(F("serviceId:SwitchPower1"));
client.print(F("&action=SetTarget"));
client.print(F("&newTargetValue="));
client.print(status ? F("1") : F("0"));
client.println(F(" HTTP/1.1"));
client.println(F("Connection: close")); //close 1.1 persistent connection
client.println(); //end of get request
delay(1);
client.stop();
}
}
void ShowSockStatus()
{
for (int i = 0; i < MAX_SOCK_NUM; i++) {
DEBUG_PRINT(F("Socket#"));
DEBUG_PRINT(i);
uint8_t s = W5100.readSnSR(i);
socketStat[i] = s;
DEBUG_PRINT(F(":0x"));
#ifdef DEBUG_ON
Serial.print(s,16);
#endif
DEBUG_PRINT(F(" "));
DEBUG_PRINT(W5100.readSnPORT(i));
DEBUG_PRINT(F(" D:"));
uint8_t dip[4];
W5100.readSnDIPR(i, dip);
for (int j=0; j<4; j++) {
Serial.print(dip[j],10);
if (j<3) Serial.print(".");
}
DEBUG_PRINT(F("("));
DEBUG_PRINT(W5100.readSnDPORT(i));
DEBUG_PRINT(F(")"));
}
}