Vera Helper with Arduino


  • Contest Winner

    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:

    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("&#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(")"));
      }
    }

  • Hero Member

    Nice, I like it.


  • Contest Winner

    @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.



  • @ServiceXp im keen, post away


  • Hero Member

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


  • Contest Winner

    @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;
    }

  • Contest Winner

    @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


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



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


  • Contest Winner

    @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...


  • Hero Member

    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?


  • Contest Winner

    @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.



  • 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


Log in to reply
 

Looks like your connection to MySensors Forum was lost, please wait while we try to reconnect.