A Proof of Concept of integration of Arduino as a transmitter for the NMEXA protocol


The design criteria of the module was

  1. Configuration done via the Home Automation GUI
  2. Status of each switch/dimmer stored in database, values retrieved via HTTP
  1. Only send data when values i database has changed
  1. Functionality to program a new NEXA reciever
  2. Support for the NEXA Dimmer

Arduino Program

    1: #include <SPI.h>
    2: #include <Ethernet.h>
    3: #include <NexaTransmitter.h>
    4:
    5: byte mac[] = {
    6:   0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF };
    7: char serverName[] = "rb";
    8: int redLedPin = 4;
    9: int greenLedPin = 9;
   10: int testButtonPin = 3;
   11: int secRun = 0;
   12:  
   13:
   14: EthernetClient client;
   15:
   16: void setup()
   17: {
   18:   pinMode(greenLedPin, OUTPUT);
   19:   pinMode(redLedPin, OUTPUT);
   20:   pinMode(testButtonPin, INPUT);
   21:   digitalWrite(testButtonPin, HIGH); // turn on internal pull up resistors
   22:
   23:   Serial.begin(115200);
   24:   if(Ethernet.begin(mac) == 0) { // start ethernet using mac & IP address
   25:     Serial.println("Failed to configure Ethernet using DHCP");  
   26:     while(true)   // no point in carrying on, so stay in endless loop:
   27:       ;
   28:   }
   29:   delay(1000); // give the Ethernet shield a second to initialize
   30:
   31:   Serial.print("connected with IP...");
   32:   Serial.println(Ethernet.localIP());
   33: }
   34:
   35: ///////////////
   36: // Main loop //
   37: ///////////////
   38: void loop()
   39: {
   40:   //Check if to program new device
   41:   if (digitalRead(testButtonPin) == LOW){
   42:     programNew();
   43:   }
   44:   //If dirty loop through and send status for all switches
   45:   if (secRun <= 0){
   46:     digitalWrite(greenLedPin, HIGH);
   47:     secRun = 10;
   48:     if (getParameter("HA.RF.SWITCH.1.ISDIRTY") == 1) { updateNEXA(getParameter("HA.RF.SWITCH.1.ID"), getParameter("HA.RF.SWITCH.1.STATUS"), false); resetParameter("HA.RF.SWITCH.1.ISDIRTY");}
   49:     if (getParameter("HA.RF.SWITCH.2.ISDIRTY") == 1) { updateNEXA(getParameter("HA.RF.SWITCH.2.ID"), getParameter("HA.RF.SWITCH.2.STATUS"), false); resetParameter("HA.RF.SWITCH.2.ISDIRTY");}
   50:     if (getParameter("HA.RF.SWITCH.3.ISDIRTY") == 1) { updateNEXA(getParameter("HA.RF.SWITCH.3.ID"), getParameter("HA.RF.SWITCH.3.STATUS"), false); resetParameter("HA.RF.SWITCH.3.ISDIRTY");}
   51:     if (getParameter("HA.RF.SWITCH.4.ISDIRTY") == 1) { updateNEXA(getParameter("HA.RF.SWITCH.4.ID"), getParameter("HA.RF.SWITCH.4.STATUS"), false); resetParameter("HA.RF.SWITCH.4.ISDIRTY");}
   52:     if (getParameter("HA.RF.SWITCH.5.ISDIRTY") == 1) { updateNEXA(getParameter("HA.RF.SWITCH.5.ID"), getParameter("HA.RF.SWITCH.5.STATUS"), false); resetParameter("HA.RF.SWITCH.5.ISDIRTY");}
   53:     if (getParameter("HA.RF.DIMMER.1.ISDIRTY") == 1) { updateNEXA(getParameter("HA.RF.DIMMER.1.ID"), getParameter("HA.RF.DIMMER.1.STATUS"), true); resetParameter("HA.RF.DIMMER.1.ISDIRTY");}
   54:     if (getParameter("HA.RF.DIMMER.2.ISDIRTY") == 1) { updateNEXA(getParameter("HA.RF.DIMMER.2.ID"), getParameter("HA.RF.DIMMER.2.STATUS"), true); resetParameter("HA.RF.DIMMER.2.ISDIRTY");}
   55:     digitalWrite(greenLedPin, LOW);
   56:   }
   57:   secRun--;
   58:   delay (1000);
   59: }
   60:
   61: //Program new reciever
   62: void programNew(){
   63:   //Blink red led 4 times
   64:   for (int i = 0; i <= 3; i++){
   65:     digitalWrite(redLedPin, HIGH); delay (200);
   66:     digitalWrite(redLedPin, LOW); delay (200);  
   67:   }
   68:   //Wait for new button press to program
   69:   while(digitalRead(testButtonPin) == HIGH){
   70:     digitalWrite(redLedPin, HIGH); delay (50);
   71:     digitalWrite(redLedPin, LOW); delay (50);  
   72:   }
   73:   //Loop through and set new data 4 times
   74:   long nexaId = getParameter("HA.RF.PROGRAM");
   75:   for (int i = 0; i <= 3; i++){
   76:     updateNEXA(nexaId, 1, false);
   77:     delay (1500);
   78:   }
   79:   digitalWrite(redLedPin, HIGH); delay (1000);
   80:   digitalWrite(redLedPin, LOW); delay (1000);  
   81: }
   82:
   83: //Check if Swithch is dirty
   84: int switchIsDirty(){
   85:   int result = 0;
   86:   result = getParameter("HA.RF.SWITCH.ISDIRTY");
   87:   return result;    
   88: }
   89:
   90: //
   91:
   92: //Send switch status
   93: void updateNEXA(long nexaId, int newStatus, boolean isDimmer){
   94:   int nexaPin = 5;
   95:   NexaTransmitter remote(nexaPin,  nexaId); // Create the nexa remote on pin2 with remote id
   96:   Serial.print("ID/Stat/Dimmer...");
   97:   Serial.print(nexaId);
   98:   Serial.print("...");
   99:   Serial.print(newStatus);
  100:   Serial.print("...");
  101:   Serial.println(isDimmer);
  102:   //Turn off
  103:   if (newStatus == 0){
  104:     if (!isDimmer) {
  105:       remote.setSwitch(false, 0);
  106:     };
  107:     if (isDimmer) {
  108:       remote.setSwitch(false, 0, 0);
  109:     };
  110:   } else {
  111:     if (!isDimmer) {
  112:       remote.setSwitch(true, 0);
  113:     };
  114:     if (isDimmer) {
  115:       remote.setSwitch(true, 0, newStatus);
  116:     };
  117:   }
  118:   //   remote.setSwitch(true, 2, 10); // switch on the unit 2 to dim level 10 (out of 15)
  119:   //   delay(3000); // wait 3 sec
  120:   //   remote.setSwitch(false, 2); // switch off the unit 2
  121: }
  122:
  123: //Set data to webserver
  124: void resetParameter(String parameter){
  125:   long result = 0;
  126:   String argumentHTTP = String("GET /ha/setvalue.php?A_N=" + parameter + "&A_T=integer&A_V=0 HTTP/1.0");
  127:
  128:   if (client.connect(serverName, 80)>0) {
  129:     //    Serial.print(argumentHTTP);
  130:     client.println(argumentHTTP);
  131:     client.println("User-Agent: Arduino/Botanicall");
  132:     client.println();
  133:   }
  134:   else
  135:   {
  136:     Serial.println("connection failed");
  137:   }
  138:
  139:   if (client.connected()) {
  140:     if(client.find("<S>True</S>")){
  141:       result = 1;
  142:     }
  143:     else
  144:     {
  145:       result = 0;
  146:     }
  147:     client.stop();
  148:     //    Serial.print("...and result:...");
  149:     //    Serial.println(result);
  150:   }
  151:   else {
  152:     client.stop();
  153:     delay(1000);
  154:   }
  155: }
  156:
  157: //Get data from webserver
  158: long getParameter(String parameter){
  159:   long result = 0;
  160:   String argumentHTTP = String("GET /ha/getvalue.php?A_N=" + parameter + " HTTP/1.0");
  161:
  162:   if (client.connect(serverName, 80)>0) {
  163: //    Serial.print(argumentHTTP);
  164:     client.println(argumentHTTP);
  165:     client.println("User-Agent: Arduino/Botanicall");
  166:     client.println();
  167:   }
  168:   else
  169:   {
  170:     Serial.println("connection failed");
  171:   }
  172:
  173:   if (client.connected()) {
  174:     if(client.find("<A_V>")){
  175:       result = client.parseInt();
  176: //      Serial.print("...and result:...");
  177: //      Serial.println(result);
  178:     }
  179:     client.stop();
  180:   }
  181:   else {
  182:     client.stop();
  183:     delay(1000);
  184:   }
  185:   return result;
  186: }