Skip to content
  • MySensors
  • OpenHardware.io
  • Categories
  • Recent
  • Tags
  • Popular
Skins
  • Light
  • Brite
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Brand Logo
  1. Home
  2. My Project
  3. Vera Helper with Arduino

Vera Helper with Arduino

Scheduled Pinned Locked Moved My Project
13 Posts 6 Posters 8.1k Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • BulldogLowellB Offline
    BulldogLowellB Offline
    BulldogLowell
    Contest Winner
    wrote on last edited by BulldogLowell
    #1

    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:

    Screen Shot 2014-12-06 at 3.46.02 PM.png

    this sketch allow you to turn on/off a relay via a webpage or Vera, and control a vera device.

    take a look:

    https://www.youtube.com/watch?v=d1kxQCuZEJI

    #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("&#169");
              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(")"));
      }
    }
    
    1 Reply Last reply
    3
    • RJ_MakeR Offline
      RJ_MakeR Offline
      RJ_Make
      Hero Member
      wrote on last edited by
      #2

      Nice, I like it.

      RJ_Make

      BulldogLowellB 1 Reply Last reply
      0
      • RJ_MakeR RJ_Make

        Nice, I like it.

        BulldogLowellB Offline
        BulldogLowellB Offline
        BulldogLowell
        Contest Winner
        wrote on last edited by BulldogLowell
        #3

        @ServiceXp

        So I've updated this for a four line display and gave it the ability to send a message to the device from its own website:

        Screen Shot 2014-12-21 at 8.01.06 AM.png

        the Display shows lots of data points from Vera:

        Video Here

        Anyone interested I'm making one... I'll post the code... or show some more video.

        1 Reply Last reply
        1
        • D Offline
          D Offline
          dayve218
          wrote on last edited by
          #4

          @ServiceXp im keen, post away

          RJ_MakeR BulldogLowellB 3 Replies Last reply
          0
          • D dayve218

            @ServiceXp im keen, post away

            RJ_MakeR Offline
            RJ_MakeR Offline
            RJ_Make
            Hero Member
            wrote on last edited by
            #5

            @dayve218 I think you mean @BulldogLowell ... ;-)

            RJ_Make

            1 Reply Last reply
            0
            • D dayve218

              @ServiceXp im keen, post away

              BulldogLowellB Offline
              BulldogLowellB Offline
              BulldogLowell
              Contest Winner
              wrote on last edited by
              #6

              @dayve218

              well, having some free time I've expanded it quite a bit, and I am not 100% sure it will run on an UNO... It works on a mega. I added a bunch of stuff:

              • tells you how many unread emails you have using a BASH script on a server to send updates every so often (I'll post that too).

              • control the brightness of the LCD with a dimmer.

              • uses Vera dimmer and switch to control relay and brightness (uses standard xml files to upload to Vera)

              • more weather

              I don't have a display demo right now, been testing in my Serial Monitor

              I can help you with any of it:

              /*
               Vera Auxilliary Controller a.k.a. Arduino/Vera Ethernet Device
               
               December, 2014
               
               Version .91 
               
               This sketch features the following:
               
               * With the device's own website it allows you to send the device a message along with a visual or sound indicator
               * Control LCD backlight
               * Control led (relay) 
               * Control your alarm state or lights or execute scenes...
               * Control attached Relay
               * Processes and displays "Vital" data from Vera like the Weather, Alarm State
               * Reliably runs on an UNO but very expandable if you want to use a Mega instead
               * Displays Indoor Temp and Humidity using DHT sensor
               
               INSTRUCTIONS:
               
               * There are multiple debug serial prints that can be monitored to assure that it is operating properly.
               * https://bitbucket.org/fmalpartida/new-liquidcrystal/downloads for the I2C library, or use yours
               * Add virtual switches to your Vera by following instructions here:http://faq.mios.com/content/2/40/en/how-to-create-virtual-device.html
               * and create a scene and add luup (lua) code like this:
                 local state = luup.variable_get("urn:upnp-org:serviceId:SwitchPower1", "Status", 3)
                 luup.inet.wget("192.168.1.50//?ledState=“..state..”&”)
               
               copyright (c) by Jim Brower (BulldogLowell@gmail.com)
               */
              #include <Wire.h>
              #include <EEPROM.h>
              #include <SPI.h>   
              //#include <SD.h>  // you will need a MEGA for this, if you want to really expand the web UI
              #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   // comment out getNTPtime(); in loop to get this to fit on an UNO for debug, otherwise debug on a MEGA
              //#define USE_DHCP   // uncomment here for DHCP but uses more than 3kBytes, so warm up your MEGA it is too big for your UNO
              #define DIMMER_PIN 6                // available PWM capable pin
              #define DHT_SENSOR_PIN 7            // Thermometer-Hygrometer
              #define RELAY_PIN 13//8                 // Relay control output
              #define DISPLAY_UPDATE_TIME 3000UL  // 3.5 seconds seems OK
              #define NUMBER_OF_MESSAGE_TYPES 17  // Kinds of transmissions from Vera/Internet
              #define TONE_PIN 6                  // If you want Audio alerts
              #define NUMBER_OF_ACTION_BUTTONS 5  // your device can control scenes, devices, etc Vera-side
              //
              #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
              //
              typedef enum{
                LCD_WIND, LCD_TIME, LCD_ALARM_STATUS, LCD_GARAGE, LCD_GUEST_GARAGE, LCD_IP_ADDRESS, LCD_TEMPERATURE, LCD_AC_SETPOINT, LCD_OUTSIDE_TEMP, LCD_WEATHER, LCD_FORECAST, LCD_MESSAGE, LCD_HI_LOW, LCD_EMAIL} 
              lcdState;
              //
              lcdState state = LCD_TIME;  // display start on Time
              //
              //File webFile;
              //
              char *messagePtr;
              const char *messageType[NUMBER_OF_MESSAGE_TYPES] = {
                "?ledStatus=", "?alarmState=", "?garageState=", "?guestGarageState=", "?weatherCondition=", "?outsideTemp=", "?outsideHumid=", "?airconSetpoint=", "?weatherForecast=", "?messageData=", "?todayHigh=", "?todayLow=", "?windSpeed=", "?windDirection=", "?relayState=", "?brightLevel=", "?emailCount="};
              //
              boolean messageFlag = false;
              unsigned long timerStart;
              unsigned long timerDuration;
              int signal = 0;
              //
              boolean lightOn;
              boolean relayState;
              boolean garageOpen = false;
              boolean guestGarageOpen = false;
              char customMessage [30];
              char weatherCondition[30] = {
                "  Not Yet Reported"};
              char weatherForecast[30] = {
                "  Not Yet Reported"};  
              int outdoorTemp = -99;
              int outdoorHumid = -99;
              int todayHigh = -99;
              int todayLow = -99;
              int airconSetpoint = 78;
              int alarmArmed = -1;
              int windSpeed = 99;
              char windDirection[6] = {"ZZZ"};
              char myCharBuffer[30];
              byte brightLevel = 0;
              byte oldBrightLevel;
              int emailCount = -1;
              //
              byte buttonPin[NUMBER_OF_ACTION_BUTTONS] = {
                4, 5, A0, A1, A2};
              byte lastButtonState[4];
              //
              DHT dht;
              //
              LiquidCrystal_I2C lcd(0x27, 20,4);
              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 };
              IPAddress ip(192,168,1,50);
              //
              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 veraServer[] = { 
                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;
              //
              void setup() 
              {
                SERIAL_START(9600);
                lightOn = EEPROM.read(0);
                relayState = EEPROM.read(1);
                pinMode(RELAY_PIN, OUTPUT);
                pinMode(DIMMER_PIN, OUTPUT);
                digitalWrite(RELAY_PIN, relayState? HIGH : LOW);
                //
                for (byte i = 0; i < 4; i++)
                {
                  pinMode(buttonPin[i], INPUT_PULLUP);
                }
                //
                dht.setup(DHT_SENSOR_PIN);
                //
              #ifdef USE_DHCP  
                 DEBUG_PRINTLN(F("configuring e-net"));
                 if (Ethernet.begin(mac) == 0) // start Ethernet and UDP
                 {
                 DEBUG_PRINTLN(F("Fail Ethernet DHCP")); 
                 while(true){
                 }
                 }
              #else
                Ethernet.begin(mac, ip);
              #endif
                //
                server.begin();
                Udp.begin(localPort);
                //
                lcd.init();
                lcd.clear();
                lightOn? lcd.backlight() : lcd.noBacklight();
                lcd.createChar(0, clock);
              }
              //
              void loop()
              {
                updateLCD();
                getNTPtime();
                webControl();
                messageTimer();
                updateBriteness();
                for (byte i = 0; i < NUMBER_OF_ACTION_BUTTONS; i++)
                {
                  byte buttonState = digitalRead(buttonPin[i]);
                  if (buttonState == LOW && lastButtonState[i] == HIGH)
                  {
                    buttonPress(i);
                  }
                  lastButtonState[i] = buttonState;
                }
              }
              //
              void updateLCD()
              {
                static unsigned long lastDisplayChangeTime;
                if (millis() - lastDisplayChangeTime >= DISPLAY_UPDATE_TIME)
                {
                  switch (state) 
                  {
                  case LCD_TIME:
                    fastClearLCD();
                    lcd.setCursor(0,0);
                    timeDate();
                    lcd.setCursor(0,1);
                    DEBUG_PRINT(F("Time: "));
                    DEBUG_PRINT(hourFormat12());
                    DEBUG_PRINT(F(":"));
                    DEBUG_PRINT(minute());
                    DEBUG_PRINTLN(isAM() ? "a" : "p");
                    DEBUG_PRINTLN(dayOfWeek[weekday()]);
                    lcd.print(dayOfWeek[weekday()]);
                    displayStatus();
                    if (emailCount != -1)
                      state = LCD_EMAIL;
                    else
                      state = LCD_ALARM_STATUS;
                    break;
                    //
                  case LCD_EMAIL:
                    fastClearLCD();
                    lcd.setCursor(0,0);
                    timeDate();
                    lcd.setCursor(0,1);
                    lcd.print(F("    Email Count"));
                    DEBUG_PRINT(F("emails: "));
                    lcd.setCursor(0,2);
                    lcd.print(F("         "));
                    lcd.print(emailCount);
                    DEBUG_PRINTLN(emailCount);
                    displayStatus();
                    state = LCD_ALARM_STATUS;
                    break;
                    //
                  case LCD_ALARM_STATUS:
                    fastClearLCD();
                    lcd.setCursor(0,0);
                    timeDate();
                    lcd.setCursor(0,1);
                    lcd.print(F("    Alarm Status"));
                    DEBUG_PRINT(F("Alm: "));
                    lcd.setCursor(0,2);
                    if (alarmArmed == 0)
                    {
                      lcd.print(F("     Not  Armed"));
                    }
                    else if (alarmArmed == 1)
                    {
                      lcd.print(F("        Armed"));
                    }
                    else
                    {
                      lcd.print(F("  Not Yet Reported"));
                    }
                    DEBUG_PRINTLN(alarmArmed ? F("Yes") : F("NO"));
                    displayStatus();
                    state = LCD_GARAGE;
                    break;
                    //
                  case LCD_GARAGE:
                    fastClearLCD();
                    lcd.setCursor(0,0);
                    timeDate();
                    lcd.setCursor(0,1);
                    lcd.print(F("    Main  Garage"));
                    DEBUG_PRINT(F("Garage: "));
                    lcd.setCursor(0,2);
                    if (garageOpen == 0)
                    {
                      lcd.print(F("       Closed"));
                    }
                    else if (garageOpen == 1)
                    {
                      lcd.print(F("        Open"));
                    }
                    else
                    {
                      lcd.print(F("  Not Yet Reported"));
                    }
                    DEBUG_PRINTLN(garageOpen ? F("OPEN") : F("CLOSE"));
                    displayStatus();
                    state = LCD_GUEST_GARAGE;
                    break;
                    //
                  case LCD_GUEST_GARAGE:
                    fastClearLCD();
                    lcd.setCursor(0,0);
                    timeDate();
                    lcd.setCursor(0,1);
                    lcd.print(F("    Guest Garage"));
                    DEBUG_PRINT(F("Guest: "));
                    lcd.setCursor(0,2);
                    if (guestGarageOpen == 0)
                    {
                      lcd.print(F("       Closed"));
                    }
                    else if (guestGarageOpen == 1)
                    {
                      lcd.print(F("        Open"));
                    }
                    else
                    {
                      lcd.print(F("  Not Yet Reported"));
                    }
                    DEBUG_PRINTLN(guestGarageOpen ? F("OPEN") : F("CLOSE"));
                    displayStatus();
                    state = LCD_TEMPERATURE;
                    break;
                    //
                  case LCD_TEMPERATURE:
                    fastClearLCD();
                    lcd.setCursor(0,0);
                    timeDate();
                    lcd.setCursor(0,1);
                    lcd.print(F("  Temperture:"));
                    DEBUG_PRINT(F("Inside Temp:"));
                    lcd.print(dht.toFahrenheit(dht.getTemperature()), 0);
                    lcd.print(char(223));
                    lcd.print(F("F"));
                    lcd.setCursor(0,2);
                    lcd.print(F("    Humidity:"));
                    lcd.print(dht.getHumidity(), 0);
                    DEBUG_PRINT(F("Humidity:"));
                    DEBUG_PRINTLN(dht.getHumidity());
                    lcd.print(F("%"));
                    displayStatus();
                    state = LCD_AC_SETPOINT;
                    break;
                  case LCD_AC_SETPOINT:
                    //
                    fastClearLCD();
                    lcd.setCursor(0,0);
                    timeDate();
                    lcd.setCursor(0,1);
                    lcd.print(F("    A/C Setpoint"));
                    lcd.setCursor(0,2);
                    lcd.print(F("        "));
                    lcd.print(airconSetpoint);
                    lcd.print(char(223));
                    lcd.print(F("F"));
                    DEBUG_PRINT(F("A/C setpoint:"));
                    DEBUG_PRINTLN(airconSetpoint);
                    displayStatus();
                    state = LCD_OUTSIDE_TEMP;
                    break;
                    //
                  case LCD_OUTSIDE_TEMP:
                    //
                    fastClearLCD();
                    lcd.setCursor(0,0);
                    timeDate();
                    lcd.setCursor(0,1);
                    lcd.print(F(" Outdoor Temp:"));
                    DEBUG_PRINT(F("Ext. Temp:"));
                    lcd.print(outdoorTemp);
                    lcd.print(char(223));
                    lcd.print(F("F"));
                    DEBUG_PRINTLN(outdoorTemp);
                    lcd.setCursor(0,2);
                    lcd.print(F("     Humidity:"));
                    DEBUG_PRINT(F("Humidity:"));
                    lcd.print (outdoorHumid);
                    lcd.print(F("%"));
                    DEBUG_PRINTLN(outdoorHumid);
                    displayStatus();
                    state = LCD_WEATHER;
                    break;
                    //
                  case LCD_WEATHER:
                    //
                    fastClearLCD();
                    lcd.setCursor(0,0);
                    timeDate();
                    lcd.setCursor(0,1);
                    lcd.print(F("  Today's  Weather"));
                    DEBUG_PRINT(F("Weather: "));
                    lcd.setCursor(0,2);
                    lcd.print(weatherCondition);
                    DEBUG_PRINTLN(weatherCondition);
                    displayStatus();
                    state = LCD_HI_LOW;
                    break;
                    //
                  case LCD_HI_LOW:
                    //
                    fastClearLCD();
                    DEBUG_PRINTLN(F("Weather Hi/Lows"));
                    timeDate();
                    lcd.setCursor(0,1);
                    lcd.print(F("Today's High: "));
                    lcd.print(todayHigh);
                    lcd.print(char(223));
                    lcd.print(F("F"));
                    lcd.setCursor(0,2);
                    lcd.print(F("         Low: "));
                    lcd.print (todayLow);
                    lcd.print(char(223));
                    lcd.print(F("F"));
                    displayStatus();
                    if (windSpeed > 2)
                    {
                      state = LCD_WIND;
                    }
                    else
                    {
                      state = LCD_FORECAST;
                      DEBUG_PRINTLN(F("wind too light to report..."));
                    }
                    break;
                    // 
                  case LCD_WIND:
                    //
                    fastClearLCD();
                    lcd.setCursor(0,0);
                    timeDate();
                    lcd.setCursor(0,1);
                    lcd.print(F("   Winds  Gusting"));
                    DEBUG_PRINT(F("Winds: "));
                    DEBUG_PRINTLN(windSpeed);
                    lcd.print(F(" "));
                    lcd.setCursor(1,2);
                    if (windSpeed < 10) lcd.print(F(" "));
                    lcd.print(windSpeed);
                    lcd.print(F("mph from the "));
                    lcd.print(windDirection);
                    displayStatus();
                    state = LCD_FORECAST;
                    break; 
                  case LCD_FORECAST:
                    //
                    fastClearLCD();
                    lcd.setCursor(0,0);
                    timeDate();
                    lcd.setCursor(0,1);
                    lcd.print(F("      Tomorrow"));
                    DEBUG_PRINT(F("Forecast: "));
                    lcd.setCursor(0,2);
                    lcd.print(weatherForecast);
                    DEBUG_PRINTLN(weatherForecast);
                    displayStatus();
                    if (messageFlag)
                      state = LCD_MESSAGE;
                    else 
                      state = LCD_IP_ADDRESS;
                    break;
                    //  
                  case LCD_MESSAGE:
                    //
                    fastClearLCD();
                    lcd.setCursor(0,0);
                    timeDate();
                    if (signal == 2 && lightOn == 1)
                    {
                      for (int i = 0; i < 20; i++)
                      {
                        lcd.noBacklight();
                        delay(50);
                        lcd.backlight();
                        delay(50);
                      }
                    }
                    else if (signal == 1 && lightOn == 1)
                    {
                      beepTone();
                    }
                    if (signal != 0) 
                    {
                      lastDisplayChangeTime - millis();  // give the message back the time lost in the flash/blinking
                    }
                    lcd.setCursor(0,1);
                    lcd.print(F("  *** Message ***"));
                    DEBUG_PRINT(F("Message: "));
                    lcd.setCursor(0,2);
                    lcd.print(customMessage);
                    DEBUG_PRINTLN(customMessage);
                    displayStatus();
                    state = LCD_IP_ADDRESS;
                    break;
                    //
                  case LCD_IP_ADDRESS:
                    //
                    fastClearLCD();
                    lcd.setCursor(0,0);
                    timeDate();
                    lcd.setCursor(0,1);
                    lcd.print(F("     IP Address"));
                    DEBUG_PRINT(F("IP Address: "));
                    lcd.setCursor(0,2);
                    lcd.print("    ");
                    for (byte thisByte = 0; thisByte < 4; thisByte++) // print the value of each byte of the IP address:
                    {
                      lcd.print(Ethernet.localIP()[thisByte], DEC);
                      if (thisByte < 3) lcd.print(".");
              #ifdef DEBUG_ON
                      Serial.print(Ethernet.localIP()[thisByte], DEC);
              #endif
                      if (thisByte < 3) DEBUG_PRINT(".");
                      else DEBUG_PRINTLN(F(" "));
                    }
                    lcd.print(F(" "));
                    displayStatus();
                    state = LCD_TIME;
                    break;
                    //      
                  }
                  lastDisplayChangeTime = millis();
                  DEBUG_PRINT(F("free ram:"));
                  DEBUG_PRINTLN(freeRam());
                } 
              }
              //
              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(19,0);
                lcd.print(F(" "));
              }
              //
              void getNTPtime()
              {
                static unsigned long lastUpdateTime;
                const unsigned long interval = 60000UL;
                if ((millis() - lastUpdateTime >= interval))
                {                                                         
                  lcd.setCursor(19,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
                    lastUpdateTime += interval;
                  }
                }
              }
              //
              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);
                        // Send a full website with controls functions and handles message input...
                        client.println(F(
                          "<html>"
                          "<head>"
                          "<title>Vera Helper</title>"
                          "</head>"
                          "<body>"
                          "<div align=\"center\">"
                          "<H2>Arduino Auxilliary Controller</H2>"
                          "<H3>for Vera</H3>"
                          "<hr>"
                          "<H2><font color=\"green\">Comfort Settings</H2>"
                          "<H4><font color=\"blue\">Temperature</font>"
                          "<font color=\"red\">"));
                        client.println(dht.toFahrenheit(dht.getTemperature()), 1);
                        client.println(F("</font>"
                          "<font color=\"blue\">F</font>"
                          "<br />"
                          "<H4><font color=\"blue\">Humidity</font>"
                          "<font color=\"red\">"));
                        client.println(dht.getHumidity(), 1);
                        client.println(F("</font>"
                          "<font color=\"blue\">%</font>"
                          "<H4><font color=\"midnightBlue\">AirConditioning Setpoint</font>"
                          "<font color=\"red\">"));
                        client.println(airconSetpoint);
                        client.println(F("</font>"
                          "<font color=\"blue\">F</font>"
                          "<br />"
                          "<hr>"
                          "<h2>"
                          "Send Message<br>"
                          "<form>"
                          "<input type=\"text\" size=\"20\" name= \"messageData\" value=\"Enter message here\">"
                          "<select name=\"time\">"
                          "<option value=\"5\">5min</option>"
                          "<option value=\"15\">15min</option>"
                          "<option selected value=\"30\">30min</option>"
                          "<option value=\"60\">60min</option>"
                          "<option value=\"720\">12hrs</option>"
                          "<option value=\"1440\">24hrs</option>"
                          "</select>"
                          "<h4>"
                          "<div align=\"center\">"
                          "<input type=\"radio\" name=\"signal\" value=\"2\"> Flash<br>"
                          "<input type=\"radio\" name=\"signal\" value=\"1\"> Tone <br>"
                          "<input type=\"radio\" name=\"signal\" value=\"0\" checked> None</h4>"
                          "<input type=\"submit\" onclick=\"alert('Message Sent!')\" value=\"Send\"> <input type=\"reset\" value=\"Reset\"></h2>"
                          "</form>"
                          "<hr>"
                          "<a href=\"/?ledStatus=1?\"\">Turn On LED Backlight</a>    "
                          "<a href=\"/?ledStatus=0?\"\">Turn Off LED Backlight</a>"
                          "<br />"
                          "<a href=\"/?relayState=1?\"\">Turn On Outlet</a>    "
                          "<a href=\"/?relayState=0?\"\">Turn Off Outlet</a><br /> "
                          "<br />"
                          "<a href=\"/?airconSetpoint="));
                        if (airconSetpoint > 70) client.println(airconSetpoint - 1);
                        else client.println(airconSetpoint);
                        client.println(F("?\"\">Lower Air Conditioning Setpoint</a><br /> "
                          "<br />"
                          "<div style=\"background-color:LightSlateGray; color:black; margin:20px; padding:20px;\">"
                          "<h3>Jim Brower</h3>"
                          "<h5>&copy; copyright 2014</h5>"
                          "<h5><a href=\"mailto:bulldoglowell@gmail.com?subject=Arduino/Vera Home Controller\">"
                          "Send Email</a><h5>"
                          "</div>"
                          "</body>"
                          "</html>"));
                        delay(1);
                        client.stop();
                        //
                        // let's sort out that HTTP request...
                        //
                        for (byte i = 0; i < NUMBER_OF_MESSAGE_TYPES; i++)
                        {
                          messagePtr = strstr(myString, messageType[i]); // we need a global variable here
                          if (messagePtr)
                          {
                            DEBUG_PRINT(F("network msg..."));
                            DEBUG_PRINTLN(messageType[i]);
                            processMessage(i);
                            break;
                          }
                        }
                        myString[0] = '\0'; //clearing string for next read
                        locator = 0;
                      }
                    }
                  }
                }
              }
              //
              #ifdef DEBUG_ON
              int freeRam () 
              {
                extern int __heap_start, *__brkval; 
                int v; 
                return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval); 
              }
              #endif
              //
              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);
              #ifdef DEBUG_ON
                  for (int j=0; j<4; j++) 
                  {
                    Serial.print(dip[j],10);
                    if (j<3) Serial.print(".");
                  }
              #endif
                  DEBUG_PRINT(F("("));
                  DEBUG_PRINT(W5100.readSnDPORT(i));
                  DEBUG_PRINT(F(")"));
                }
              }
              //
              void processMessage(byte httpMessage)
              {
                switch (httpMessage)
                {
                case 0: // "?ledStatus="
                  //
                  lightOn = parseNumber(httpMessage) ? 1 : 0;
                  //(myString[messagePtr - myString + strlen(messageType[httpMessage])]) == '0' ? lightOn = 0 : lightOn = 1;
                  EEPROM.write(0, lightOn? 0xFF : 0x00);
                  if (lightOn) lcd.backlight();
                  else lcd.noBacklight();
                  DEBUG_PRINT(F("LCD Backlight: "));
                  DEBUG_PRINTLN(lightOn ? F("ON") : F("OFF"));
                  break;
                case 1: // "?alarmState="
                  //
                  alarmArmed = parseNumber(httpMessage) ? 1 : 0;
                  DEBUG_PRINTLN(alarmArmed ? F("Alarm is ON") : F("Alarm is OFF"));
                  break;
                case 2: // "?garageState=" 
                  //
                  garageOpen = parseNumber(httpMessage) ? 1 : 0;
                  DEBUG_PRINTLN(garageOpen ? F("Garage is Open") : F("garage is Closed"));
                  break;
                case 3: // "?guestGarageState="
                  //
                  guestGarageOpen = parseNumber(httpMessage) ? 1 : 0;
                  DEBUG_PRINTLN(guestGarageOpen ? F("Guest garage is Open") : F("Guest garage is Closed"));
                  break;
                case 4: // "?weatherCondition="  // Parse Weather 
                  //
                  {
                    strncpy(weatherCondition, parseString(httpMessage), sizeof weatherCondition);
                    DEBUG_PRINTLN(weatherCondition);
                    if (strstr(weatherCondition, "%20"))
                    {
                      strncpy(weatherCondition, cleanString(weatherCondition, "%20"), sizeof weatherCondition);
                      DEBUG_PRINTLN(weatherCondition);
                    }
                    if (strlen(weatherCondition) < 19) 
                    {
                      strncpy(weatherCondition, centerString(weatherCondition), sizeof weatherCondition);
                    }
                  }
                  break;
                case 5: // "?outsideTemp="  // Parse Outside Temperature 
                  //
                  outdoorTemp = parseNumber(httpMessage);
                  break;
                case 6: // "?outsideHumid=" // Parse Outside Humidity 
                  //
                  outdoorHumid = parseNumber(httpMessage);
                  break;
                case 7: // "?airconSetpoint="  // Parse A/C Setpoint 
                  //
                  airconSetpoint = parseNumber(httpMessage);
                  break;
                case 8: // "?weatherForecast="  // Parse the weather forecast
                  //
                  {
                    strncpy(weatherForecast, parseString(httpMessage), sizeof weatherForecast);
                    DEBUG_PRINTLN(weatherForecast);
                    if (strstr(weatherForecast, "+"))
                    {
                      strncpy(weatherForecast, cleanString(weatherForecast, "+"), sizeof weatherForecast);
                      DEBUG_PRINTLN(weatherForecast);
                    }
                    if (strlen(weatherForecast) < 19) 
                    {
                      strncpy(weatherForecast, centerString(weatherForecast), sizeof weatherForecast);
                    }
                  }
                  break;
                case 9: //"?messageData="  // Parse display message
                  //
                  {
                    strncpy(customMessage, parseString(httpMessage), sizeof customMessage);
                    if (strstr(customMessage, "+"))
                    {
                      strncpy(customMessage, cleanString(customMessage, "+"), sizeof customMessage);
                      DEBUG_PRINTLN(customMessage);
                    }
                    if (strlen(customMessage) < 19) 
                    {
                      strncpy(customMessage, centerString(customMessage), sizeof customMessage);
                    }
                    Serial.println(myString);
                    if (strstr(myString, "&time="))
                    {
                      DEBUG_PRINTLN(F("Got length marker..."));
                      char *timePointer = (strstr(myString, "&time="));
                      timerDuration = atoi(timePointer + 6);
                      timerStart = millis();
                      DEBUG_PRINT(F("message length:"));
                      DEBUG_PRINTLN(timerDuration);
                    }
                    else
                    {
                      DEBUG_PRINTLN(F("No length marker..."));
                      timerDuration = 5;
                    }
                    if (strstr(myString, "&signal="))
                    {
                      DEBUG_PRINTLN(F("Got signal..."));
                      char *signalPointer = (strstr(myString, "&signal="));
                      signal = atoi(signalPointer + 8);
                      timerStart = millis();
                      DEBUG_PRINT(F("Signal ="));
                      DEBUG_PRINTLN(signal);
                    }
                    else
                    {
                      DEBUG_PRINTLN(F("No signal..."));
                      timerDuration = 5;
                    }
                    timerStart = millis();
                    messageFlag = true;
                  }
                  break;
                case 10: // "?todayHigh="  // Parse Outside High Temperature 
                  //
                  todayHigh = parseNumber(httpMessage);
                  break;
                case 11: // "?todayLow="  // Parse Outside Low Temperature 
                  //
                  todayLow = parseNumber(httpMessage);
                  break;
                case 12: // "?windSpeed="  // Parse Outside Low Temperature 
                  //
                  windSpeed = parseNumber(httpMessage);
                  break;
                case 13: // "?windDirection"  // Parse Outside Low Temperature 
                  //
                  strncpy(windDirection, parseString(httpMessage), sizeof windDirection);
                  break;
                  //
                case 14:  //  "?relayState=" // Get the state of the relay
                //
                  relayState = parseNumber(httpMessage) ? 1 : 0;
                  //(myString[messagePtr - myString + strlen(messageType[httpMessage])]) == '0' ? relayState = 0 : relayState = 1;
                  EEPROM.write(1, relayState ? 0xFF : 0x00);
                  digitalWrite(RELAY_PIN, relayState ? HIGH : LOW);
                  DEBUG_PRINT(F("Relay Status: "));
                  DEBUG_PRINTLN(relayState ? F("ON") : F("OFF"));
                  break;
                  //
                case 15:  //  "?brightLevel=" // Get the brightness of the LED
                //
                  brightLevel = parseNumber(httpMessage);
                  brightLevel = map(brightLevel, 0, 100, 0, 255);
                  DEBUG_PRINT(F("Brite:"));
                  DEBUG_PRINTLN(brightLevel);
                  break;
                  //
                case 16: // "?emailCount"  // Parse email count 
                  //
                  emailCount = parseNumber(httpMessage);
                  break;
                default:
                  {
                    //Nothing to do here...
                  }
                } 
              }
              //
              void buttonPress(int buttonID)
              {
                DEBUG_PRINTLN(F("buttonPress"));
                ShowSockStatus();
                if (client.connect(veraServer, 3480)) //starts client connection, checks for connection
                {  
                  DEBUG_PRINTLN(F("connected"));
                  switch (buttonID)
                  {
                    case 0:  // Toggle LED backlight (?ledStatus=)
                      //
                      client.print(F("GET /data_request?"
                        "id=action&output_format=xml"
                        "&DeviceNum=111" // <<<<< Set Vera Device Number for LCD backlight
                        "&serviceId=urn:upnp-org:"
                        "serviceId:SwitchPower1"
                        "&action=SetTarget"
                        "&newTargetValue="));
                      client.println(lightOn ? F("0") : F("1"));
                      client.println(F(" HTTP/1.1"
                        "Connection: close"));  //close 1.1 persistent connection  
                      client.println(); //end of get request
                      delay(1);
                      client.stop();
                      break;
                      //
                    case 1:  // Toggle Relay (relayState)
                      //
                      client.print(F("GET /data_request?"
                        "id=action&output_format=xml"
                        "&DeviceNum=116" // <<<<< Set Vera Device Number for Relay
                        "&serviceId=urn:upnp-org:"
                        "serviceId:SwitchPower1"
                        "&action=SetTarget"
                        "&newTargetValue="));
                      client.print(relayState ? F("0") : F("1"));
                      client.println(F(" HTTP/1.1"
                        "Connection: close"));  //close 1.1 persistent connection  
                      client.println(); //end of get request
                      delay(1);
                      client.stop();
                      break;
                      //
                    case 2:  // Toggle Alarm
                      //
                      client.print(F("GET /data_request?"
                        "id=action&output_format=xml"
                        "&DeviceNum=112" /* <<<<< Set Vera Device Number for Alarm */
                        "&serviceId=urn:upnp-org:"
                        "serviceId:SwitchPower1"
                        "&action=SetTarget"
                        "&newTargetValue="));
                      client.print(relayState ? F("0") : F("1"));
                      client.println(F(" HTTP/1.1"
                        "Connection: close"));  //close 1.1 persistent connection  
                      client.println(); //end of get request
                      delay(1);
                      client.stop();
                      break;
                      //
                    case 3:  // run lights out scene  //<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
                      //
                      client.print(F("GET /data_request?"
                        "id=action&output_format=xml"
                        "&DeviceNum=112" /* <<<<< Set Vera Device Number for Alarm */
                        "&serviceId=urn:upnp-org:"
                        "serviceId:SwitchPower1"
                        "&action=SetTarget"
                        "&newTargetValue="));
                      client.print(relayState ? F("0") : F("1"));
                      client.println(F(" HTTP/1.1"
                        "Connection: close"));  //close 1.1 persistent connection  
                      client.println(); //end of get request
                      delay(1);
                      client.stop();
                      break;
                      //
                    case 4:  // Lower Air Conditioning //<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
                      //
                      client.print(F("GET /data_request?"
                        "id=action&output_format=xml"
                        "&DeviceNum=112" /* <<<<< Set Vera Device Number for A/C Control */
                        "&serviceId=urn:upnp-org:"
                        "serviceId:SwitchPower1"
                        "&action=SetTarget"
                        "&newTargetValue="));
                      if (airconSetpoint > 72) client.print(airconSetpoint - 1);
                      else client.print(airconSetpoint - 1);
                      client.println(F(" HTTP/1.1"
                        "Connection: close"));  //close 1.1 persistent connection  
                      client.println(); //end of get request
                      delay(1);
                      client.stop();
                      break;
                      //
                    default:
                    {
                      //nothing to do here...
                    }
                  }
                }
              }
              //
              char *parseString(byte messageNumber)
              {
                int textLocation = (messagePtr - myString + strlen(messageType[messageNumber]));
                myCharBuffer[0] = '\0';
                for (byte i = 0; i < 30; i++) // we have room to display only 20 chars, but lets parse 30.
                {
                  if (myString[textLocation + i] != '&')
                  {
                    myCharBuffer[i] = myString[textLocation + i];
                    DEBUG_PRINTLN(myCharBuffer[i]);
                  }
                  else
                  {
                    DEBUG_PRINTLN(F("got & marker"));
                    myCharBuffer[i] = '\0';
                    break;
                  }
                }
                DEBUG_PRINTLN(myCharBuffer);
                return myCharBuffer;
              }
              //
              char *cleanString(char *targetString, char *searchString)
              {
                while(strstr(targetString, searchString))
                {
                  char* stringChunk;
                  stringChunk = strstr(targetString, searchString);
                  targetString[stringChunk - targetString] = '\0';
                  strncpy(myCharBuffer, targetString, sizeof myCharBuffer);
                  strncat(myCharBuffer, " ", sizeof myCharBuffer);
                  strncat(myCharBuffer, stringChunk + strlen(searchString), sizeof myCharBuffer);
                  strncpy(targetString, myCharBuffer, sizeof myCharBuffer);
                }
                return myCharBuffer;
              }
              //
              int parseNumber(byte msgNum)
              {
                if (strstr(myString, messageType[msgNum]))
                { 
                  char *messagePointer;
                  messagePointer = strtok(myString, "=");
                  messagePointer = strtok(NULL, "?");
                  int extractedNumber = atoi(messagePointer);
                  return extractedNumber;
                }
                else
                {
                  DEBUG_PRINTLN(F("Fail parseNumber..."));
                  return -99;
                }
              }
              char *centerString(char *stringToCenter)
              {
                char centerSpacing[30];
                for (byte i = 0; i < ((20 - strlen(myCharBuffer)) / 2); i++)
                {
                  centerSpacing[i] = ' ';
                  centerSpacing[i+1] = '\0';
                }
                strncat(centerSpacing, myCharBuffer, sizeof centerSpacing);
                strncpy(myCharBuffer, centerSpacing, sizeof myCharBuffer);
                return myCharBuffer;
              }
              void messageTimer()
              {
                if (millis() - timerStart >= timerDuration * 60000UL)
                {
                  messageFlag = false;
                  signal = 0;
                }
              }
              //
              void fastClearLCD()
              {
                for (int i = 1; i < 3; i++)
                {
                  lcd.setCursor(0,i);
                  for (int j = 0; j < 20; j++)
                  {
                    lcd.print(F(" "));
                  }
                }
              }
              //
              void timeDate()
              {
                if (hourFormat12() < 10) lcd.print(F(" "));
                lcd.print(hourFormat12());
                lcd.print(minute() < 10 ? F(":0") : F(":"));
                lcd.print(minute());
                lcd.print(isAM() ? "am" : "pm");
                lcd.setCursor(11,0);
                if (month() < 10) lcd.print(F(" "));
                lcd.print(month());
                lcd.print(day() < 10 ? F("/0") : F("/"));
                lcd.print(day());
                lcd.print(F("/"));
                lcd.print(year());
              }
              //
              void displayStatus()
              {
                lcd.setCursor(0,3);
                lcd.print(F("A/C:"));
                lcd.print(airconSetpoint);  //lcd.print(dht.toFahrenheit(dht.getTemperature()), 1);
                lcd.print(char(223));
                lcd.print(F("F "));
                lcd.setCursor(11,3);
                if (alarmArmed != 1)
                {
                  lcd.print(F("Not Armed"));
                }
                else
                {
                  lcd.print(F("    Armed"));
                }
              }
              //
              void beepTone()
              {
                /*
                tone(TONE_PIN, 440, 200);
                noTone(TONE_PIN);
                */
              }
              void updateBriteness()
              {
                if (brightLevel != oldBrightLevel)
                {
                  analogWrite(DIMMER_PIN, brightLevel);
                }
                oldBrightLevel = brightLevel;
              }
              
              1 Reply Last reply
              1
              • D dayve218

                @ServiceXp im keen, post away

                BulldogLowellB Offline
                BulldogLowellB Offline
                BulldogLowell
                Contest Winner
                wrote on last edited by
                #7

                @dayve218

                BASH script to transmit unread emails to the arduino:

                #!/bin/bash
                #SCRIPT_NAME="Arduino Gmail Checker"
                #SCRIPT_VERSION="0.1"
                #figlet $SCRIPT_NAME $SCRIPT_VERSION
                #
                ###################################
                #                                 #
                # Modified for use with Vera Tool #
                #    Jim Brower  January 2015     #
                #                                 #
                #########################################################################################
                # Description: Check Gmail for unread email and switch RGB LED on Arduino in accordance #
                # Dependencies: sed, curl,                                                              #
                # Author: Virtualmix                                                                    #
                # http://blog.trollmaker.com/article10/arduino-led-notification-for-gmail-on-linux      #
                # License: CC BY                                                                        #
                #########################################################################################
                # Enter Gmail username and password below (Warning: Unsafe storage):
                USERID="username"
                PASSWORD="password"
                # Enter number of seconds between email verification:
                WAIT=60
                ########################################################################################
                #set -xv
                # Loop to check for new mail every X minutes
                while [ "1" -eq "1" ]; do
                
                    # Command line to fetch the number of unread emails:
                    MAILCOUNTER=`curl -u $USERID:$PASSWORD --silent "https://mail.google.com/mail/feed/atom" \ | xmllint --format - \ | sed -n 's#<fullcount>\(.*\)</fullcount>#\1#p'`
                    if [[ "$MAILCOUNTER" = "" ]]; then
                        echo "ERROR: The program coulndn't fetch the account for user \"$USERID\"."
                        echo "- Are you connected to the Internet?"
                        echo -e "- Is the userid and password correct for \"$USERID\"?\n"
                        curl -H "Accept: application/xml" -H "Content-Type: application/xml" -X GET 192.168.1.50/?emailCount=-1\&
                
                    elif [[ "$MAILCOUNTER" -eq "0" ]]; then
                        echo "* There is 0 new email for user $USERID."
                        curl -H "Accept: application/xml" -H "Content-Type: application/xml" -X GET 192.168.1.50/?emailCount=0&
                        # you can do other curl here....
                        
                    elif [[ "$MAILCOUNTER" -gt "0" ]]; then
                        echo "* There is $MAILCOUNTER new email for user $USERID."
                        curl -H "Accept: application/xml" -H "Content-Type: application/xml" -X GET 192.168.1.50/?emailCount="$MAILCOUNTER"&
                        # you can do other curl here....
                    fi
                
                    echo "* Waiting $WAIT seconds before checking for emails again."
                    echo "* (^C to quit the program)"
                    sleep $WAIT
                #set +xv
                done
                
                C 1 Reply Last reply
                0
                • D Offline
                  D Offline
                  dayve218
                  wrote on last edited by
                  #8

                  @BulldogLowell thanks!!! ill have a play later on!!

                  1 Reply Last reply
                  0
                  • BulldogLowellB BulldogLowell

                    @dayve218

                    BASH script to transmit unread emails to the arduino:

                    #!/bin/bash
                    #SCRIPT_NAME="Arduino Gmail Checker"
                    #SCRIPT_VERSION="0.1"
                    #figlet $SCRIPT_NAME $SCRIPT_VERSION
                    #
                    ###################################
                    #                                 #
                    # Modified for use with Vera Tool #
                    #    Jim Brower  January 2015     #
                    #                                 #
                    #########################################################################################
                    # Description: Check Gmail for unread email and switch RGB LED on Arduino in accordance #
                    # Dependencies: sed, curl,                                                              #
                    # Author: Virtualmix                                                                    #
                    # http://blog.trollmaker.com/article10/arduino-led-notification-for-gmail-on-linux      #
                    # License: CC BY                                                                        #
                    #########################################################################################
                    # Enter Gmail username and password below (Warning: Unsafe storage):
                    USERID="username"
                    PASSWORD="password"
                    # Enter number of seconds between email verification:
                    WAIT=60
                    ########################################################################################
                    #set -xv
                    # Loop to check for new mail every X minutes
                    while [ "1" -eq "1" ]; do
                    
                        # Command line to fetch the number of unread emails:
                        MAILCOUNTER=`curl -u $USERID:$PASSWORD --silent "https://mail.google.com/mail/feed/atom" \ | xmllint --format - \ | sed -n 's#<fullcount>\(.*\)</fullcount>#\1#p'`
                        if [[ "$MAILCOUNTER" = "" ]]; then
                            echo "ERROR: The program coulndn't fetch the account for user \"$USERID\"."
                            echo "- Are you connected to the Internet?"
                            echo -e "- Is the userid and password correct for \"$USERID\"?\n"
                            curl -H "Accept: application/xml" -H "Content-Type: application/xml" -X GET 192.168.1.50/?emailCount=-1\&
                    
                        elif [[ "$MAILCOUNTER" -eq "0" ]]; then
                            echo "* There is 0 new email for user $USERID."
                            curl -H "Accept: application/xml" -H "Content-Type: application/xml" -X GET 192.168.1.50/?emailCount=0&
                            # you can do other curl here....
                            
                        elif [[ "$MAILCOUNTER" -gt "0" ]]; then
                            echo "* There is $MAILCOUNTER new email for user $USERID."
                            curl -H "Accept: application/xml" -H "Content-Type: application/xml" -X GET 192.168.1.50/?emailCount="$MAILCOUNTER"&
                            # you can do other curl here....
                        fi
                    
                        echo "* Waiting $WAIT seconds before checking for emails again."
                        echo "* (^C to quit the program)"
                        sleep $WAIT
                    #set +xv
                    done
                    
                    C Offline
                    C Offline
                    cleight
                    wrote on last edited by
                    #9

                    @BulldogLowell Would it be possible to use your example without the webserver portion on a Nano and still pull information from Vera?

                    BulldogLowellB 1 Reply Last reply
                    0
                    • C cleight

                      @BulldogLowell Would it be possible to use your example without the webserver portion on a Nano and still pull information from Vera?

                      BulldogLowellB Offline
                      BulldogLowellB Offline
                      BulldogLowell
                      Contest Winner
                      wrote on last edited by
                      #10

                      @cleight

                      do you mean without ethernet using the MySensors configuration?

                      look at this example, and be sure to check out @korttoma example down the page...

                      1 Reply Last reply
                      0
                      • korttomaK Offline
                        korttomaK Offline
                        korttoma
                        Hero Member
                        wrote on last edited by
                        #11

                        I just had an idea @BulldogLowell .

                        Do you think it would be possible for your Vera Helper to write variables directly to Plot.ly using http.request?
                        How cool would that be?

                        • Tomas
                        BulldogLowellB 1 Reply Last reply
                        0
                        • korttomaK korttoma

                          I just had an idea @BulldogLowell .

                          Do you think it would be possible for your Vera Helper to write variables directly to Plot.ly using http.request?
                          How cool would that be?

                          BulldogLowellB Offline
                          BulldogLowellB Offline
                          BulldogLowell
                          Contest Winner
                          wrote on last edited by
                          #12

                          @korttoma

                          Sure... you could retrieve data from vera and transmit to plot.ly by making an http request to vera and passing it on to plot.ly.

                          I guess it is possible also to make a MySensors ethenet node and other MySensors sensors could transmit values to the Ethernet Enabled Sensor too.

                          1 Reply Last reply
                          0
                          • mntlvrM Offline
                            mntlvrM Offline
                            mntlvr
                            wrote on last edited by
                            #13

                            Hello @BulldogLowell
                            I am brand new to this site but have built a few of my own project that monitored batteries and controlled the charging rate as well as the voltage all through a web page but I am Interested in this project, Have you a complete project details with BOM and full working code, as of yet? I am looking to control the fill of a 275 gallon water tank by sonic means. I wish to have the Ultra-Sonic device measure the water level and when certain depth conditions are met the unit will open a valve and allow water in , then when the proper level is met it will close the valve and transmit all this info back to my Vera and or a web page. Please keep up the great idea.
                            Thanks

                            1 Reply Last reply
                            0
                            Reply
                            • Reply as topic
                            Log in to reply
                            • Oldest to Newest
                            • Newest to Oldest
                            • Most Votes


                            11

                            Online

                            11.7k

                            Users

                            11.2k

                            Topics

                            113.1k

                            Posts


                            Copyright 2025 TBD   |   Forum Guidelines   |   Privacy Policy   |   Terms of Service
                            • Login

                            • Don't have an account? Register

                            • Login or register to search.
                            • First post
                              Last post
                            0
                            • MySensors
                            • OpenHardware.io
                            • Categories
                            • Recent
                            • Tags
                            • Popular