Home automation using Xbee radios

Dependencies:   EthernetNetIf HTTPServer RPCInterface mbed C12832_lcd

Link to Notebook Page

Revision:
9:4b1e3531dd00
Parent:
8:e32fcca16102
Child:
10:de0be690b3c0
diff -r e32fcca16102 -r 4b1e3531dd00 main.cpp
--- a/main.cpp	Mon Dec 02 22:25:29 2013 +0000
+++ b/main.cpp	Wed Dec 04 02:35:47 2013 +0000
@@ -20,33 +20,34 @@
 #include "XbeeCommLib.h"
 
 DigitalIn pb(p8);
+DigitalOut led1(LED1);
+DigitalOut led4(LED4);
 
 Serial xbeeSerial(p9, p10);
-C12832_LCD lcd;
 
 unsigned char data[500];
 int dataCounter = 0;
 bool clear = false;
 
 //Create port variables
-float ReadTemperatureSensor1;
-float ReadTemperatureSensor2;
-int ReadMotionDetector1;
-int ReadMotionDetector2;
-int ReadLightSwitch1;
-int ReadLightSwitch2;
-int WriteLightSwitch1;
-int WriteLightSwitch2;
+float ReadTemperatureSensor0 = 0.0;
+float ReadTemperatureSensor1 = 0.0;
+int ReadMotionDetector0 = 1; //Motion detector is low-active
+int ReadMotionDetector1 = 1; //Motion detector is low-active
+int ReadLightSwitch0 = 0;
+int ReadLightSwitch1 = 0;
+int WriteLightSwitch0 = 0;
+int WriteLightSwitch1 = 0;
 
 //Make these variables accessible over RPC by attaching them to an RPCVariable
+RPCVariable<float> RPCTemperatureSensor0(&ReadTemperatureSensor0, "TemperatureSensor0");
 RPCVariable<float> RPCTemperatureSensor1(&ReadTemperatureSensor1, "TemperatureSensor1");
-RPCVariable<float> RPCTemperatureSensor2(&ReadTemperatureSensor2, "TemperatureSensor2");
+RPCVariable<int> RPCMotionDetector0(&ReadMotionDetector0, "MotionDetector0");
 RPCVariable<int> RPCMotionDetector1(&ReadMotionDetector1, "MotionDetector1");
-RPCVariable<int> RPCMotionDetector2(&ReadMotionDetector2, "MotionDetector2");
+RPCVariable<int> RPCReadLightSwitch0(&ReadLightSwitch0, "ReadLightSwitch0");
 RPCVariable<int> RPCReadLightSwitch1(&ReadLightSwitch1, "ReadLightSwitch1");
-RPCVariable<int> RPCReadLightSwitch2(&ReadLightSwitch2, "ReadLightSwitch2");
+RPCVariable<int> RPCWriteLightSwitch0(&WriteLightSwitch0, "WriteLightSwitch0");
 RPCVariable<int> RPCWriteLightSwitch1(&WriteLightSwitch1, "WriteLightSwitch1");
-RPCVariable<int> RPCWriteLightSwitch2(&WriteLightSwitch2, "WriteLightSwitch2");
 
 EthernetNetIf eth;  
 HTTPServer svr;
@@ -61,23 +62,33 @@
     int digitalType[10];
     float analogData[4];
     int analogType[4];
+    float* analogRpcDataPointer[4];
+    int* digitalOutRpcDataPointer[10];
+    int* digitalInRpcDataPointer[10];
+    Timer* timerList[10];
     struct xbee * next;    // pointer to next struct
 };
 
 struct xbee *root;
 
+struct xbee xbeeList[3];
+int xbeeCount = 3;
+
 
 
 
 void xbeeSerialCallback() {
+    //printf("Xbee\n");
     if(clear){
         dataCounter = 0;
         clear = false;
     }
     if(dataCounter < 500){
         while(xbeeSerial.readable() == true && dataCounter < 500){
+            led4 = 1;
             data[dataCounter] = xbeeSerial.getc();
             dataCounter++;
+            led4 = 0;
         }
     }
     else{
@@ -91,14 +102,14 @@
 
 int main() {
     
-    xbeeSerial.attach(&xbeeSerialCallback);
+    //xbeeSerial.attach(&xbeeSerialCallback);
     
+    printf("\n\nBeginning Setup\n");
     // Ethernet Setup
     EthernetErr ethErr = eth.setup();
-    if(ethErr)
-    {
-    printf("Error %d in setup.\n", ethErr);
-    return -1;
+    if(ethErr){
+        printf("Error %d in setup.\n", ethErr);
+        return -1;
     }
     printf("Setup OK\n");
     
@@ -107,41 +118,84 @@
     
     // Show that the server is ready and listening
     svr.bind(80);
-    printf("Listening...\n");
+    printf("RPC Server Ready\n");
   
     /* This won't change, or we would lose the list in memory */
     //struct xbee *root;
-    root->next = NULL; 
+    root = (struct xbee *) malloc( sizeof(struct xbee) );
+    root->next = NULL;
     /* The node root points to has its next pointer equal to a null pointer 
     set */
-    struct xbee* xbee1;
-    struct xbee* xbee2;
-    struct xbee* xbee3;
+    //struct xbee* xbee1;
+//    struct xbee* xbee2;
+//    struct xbee* xbee3;
+    
+//    printf("Beginning Xbee Radio Struct Setup\n");
+//    xbee1 = addnode(root, 0x0013a200, 0x4079d00b); //Router0
+//    xbee1->analogType[1] = 1;   //Analog Devices TMP36 Temp Sensor
+//    xbee1->digitalType[0] = 1;  //Light control (output)
+//    xbee1->digitalType[3] = 1;  //Motion sensor (input)
+//    xbee1->analogRpcDataPointer[1] = &ReadTemperatureSensor1;
+//    printf("xbee1 setup\n");
+    xbeeList[0].addrHigh = 0x0013a200;
+    xbeeList[0].addrLow = 0x4079d00b; //Router0
+    xbeeList[0].analogType[1] = 1;   //Analog Devices TMP36 Temp Sensor
+    xbeeList[0].digitalType[0] = 1;  //Light control (output)
+    xbeeList[0].digitalType[2] = 2;  //Motion sensor (input)
+    xbeeList[0].analogRpcDataPointer[1] = &ReadTemperatureSensor0;
+//    printf("Xbee0: Storing RPC variable address %d\nStored address is %d\n", &ReadTemperatureSensor1, xbeeList[0].analogRpcDataPointer[1]);
+    xbeeList[0].digitalOutRpcDataPointer[0] = &ReadLightSwitch0;
+    xbeeList[0].digitalInRpcDataPointer[2] = &ReadMotionDetector0;
+    Timer motionTimer0;
+    xbeeList[0].timerList[2] = &motionTimer0;
     
-    xbee1 = addnode(root, 0x0013a200, 0x4079d00b); //Router0
-    xbee1->analogType[1] = 1;   //Analog Devices TMP36 Temp Sensor
-    xbee1->digitalType[0] = 1;  //Light control (output)
-    xbee1->digitalType[3] = 1;  //Motion sensor (input)
     
-    xbee2 = addnode(root, 0x0013a200, 0x4079d023); //Router1
-    xbee2->analogType[1] = 1;   //Analog Devices TMP36 Temp Sensor
-    xbee2->digitalType[0] = 1;  //Light control (output)
+//    xbee2 = addnode(root, 0x0013a200, 0x4079d023); //Router1
+//    xbee2->analogType[1] = 1;   //Analog Devices TMP36 Temp Sensor
+//    xbee2->digitalType[0] = 1;  //Light control (output)
+//    printf("xbee2 setup\n");
+    xbeeList[1].addrHigh = 0x0013a200;
+    xbeeList[1].addrLow = 0x4079d023; //Router1
+    xbeeList[1].analogType[1] = 1;   //Analog Devices TMP36 Temp Sensor
+    xbeeList[1].digitalType[0] = 1;  //Light control (output)
+    xbeeList[1].digitalType[2] = 2;  //Motion sensor (input)
+    xbeeList[1].analogRpcDataPointer[1] = &ReadTemperatureSensor1;
+//    printf("Xbee1: Storing RPC variable address %d\nStored address is %d\n", &ReadTemperatureSensor2, xbeeList[1].analogRpcDataPointer[1]);
+    xbeeList[1].digitalOutRpcDataPointer[0] = &ReadLightSwitch1;
+    xbeeList[1].digitalInRpcDataPointer[2] = &ReadMotionDetector1;
+    Timer motionTimer1;
+    xbeeList[1].timerList[2] = &motionTimer1;
     
-    xbee3 = addnode(root, 0, 3);
-    xbee3->digitalType[3] = 1;  //Motion sensor (input)
     
+    //xbee3 = addnode(root, 0, 3);
+//    xbee3->digitalType[3] = 1;  //Motion sensor (input)
+    
+    printf("Initialization finished\n\n");
      
     // TODO: Read sensors and set RPC variables to initial values
     
+    Timer tm;
+    tm.start();
     //Main program loop
     while(true){
         Net::poll();
+        xbeeSerialCallback();
         monitorXbee();
+        compareDigitalReadWrite();
+        
+        
         // TODO: Poll sensors and reset RPC variables. 
+        
+        if(tm.read() > 1){
+            led1 = !led1;
+            tm.start();
+            
+            monitorTimers();
+        }
     }
 }
 
-struct xbee* addnode(struct xbee* root, unsigned int addrhigh, unsigned int addrlow){
+struct xbee* addnode(struct xbee* root, unsigned int addrHigh, unsigned int addrLow){
     struct xbee* node;
     node = root;
     
@@ -152,8 +206,8 @@
     }
     node = (struct xbee *) malloc( sizeof(struct xbee) );
     node->next = NULL;
-    node->addrHigh = addrhigh;
-    node->addrLow = addrlow;
+    node->addrHigh = addrHigh;
+    node->addrLow = addrLow;
     return node;
 }
 
@@ -182,15 +236,39 @@
 
 
 
-void digitalInputHandle(struct xbee* root, unsigned int addrhigh, unsigned int addrlow, unsigned short data){
-    struct xbee* node;
-    node = root;
+void digitalInputHandle(struct xbee* root, unsigned int addrHigh, unsigned int addrLow, unsigned short data){
+    //struct xbee* node;
+//    node = root;
+    
+    //printf("Digital input handler: Address: %x %x\nDigital Data = %d\n", addrHigh, addrLow, data);
+    
+    for(int i = 0; i < xbeeCount; i++){
+        if(xbeeList[i].addrHigh == addrHigh && xbeeList[i].addrLow == addrLow){
+            //Addresses match match
+            
+            //Place the digital data in the appropriate position in the struct
+            xbeeList[i].digitalData = data;
+            
+            //Need to update appropriate RPC variables
+            break;
+        }
+        if(i == (xbeeCount - 1)){
+            printf("No matching addresses found\n");
+        }
+    }
+    
+    
+    /*
+        Add code here to check for digital input changes.
+        This is important to be able to detect motion
+    */
+    
  
-    if ( node != 0 ) {
-        while ( node->addrHigh != addrhigh){          
+    /*if ( node != 0 ) {
+        while ( node->addrHigh != addrHigh){          
            node = node->next;
         }
-        while(node->addrLow !=addrlow){
+        while(node->addrLow !=addrLow){
             node = node->next;
         }
     }
@@ -203,42 +281,172 @@
     }
     else{
         printf("Node is not in the list");
-    }
-    
-    
-    /*
-        Add code here to check for digital input changes.
-        This is important to be able to detect motion
-    */
-    
+    }*/
     
 }
 
 
-void analogInputHandle(struct xbee* root,unsigned int addrhigh, unsigned int addrlow, int index, float data){
-    struct xbee* node;
-    node = root;
+void analogInputHandle(struct xbee* root,unsigned int addrHigh, unsigned int addrLow, int index, float data){
+    //struct xbee* node;
+//    node = root;
+    float analogData;
+    
+    //printf("Analog input handler: Address: %x %x\nAnalog Index = %d  Analog Value = %f\n", addrHigh, addrLow, index, data);
     
     if(index < 0){
         printf("ERROR: Analog input index is negative\n");
+        return;
+    }
+    
+    
+    for(int i = 0; i < xbeeCount; i++){
+        if(xbeeList[i].addrHigh == addrHigh && xbeeList[i].addrLow == addrLow){
+            //Addresses match match
+            if(DEBUG)
+                printf("Xbee %d radio address match\n", i);
+            
+            //Place the analog data in the appropriate position in the struct
+            analogData = analogInputFormat(data, xbeeList[i].analogType[index]);
+            xbeeList[i].analogData[index] = analogData;
+            
+            if(xbeeList[i].analogRpcDataPointer[index] != NULL){
+                //Also push the analog data to the RPC variable
+                *xbeeList[i].analogRpcDataPointer[index] = analogData;
+                //printf("Storing value %f into RPC pointer. Value stored is %f\n", analogData, *xbeeList[i].analogRpcDataPointer[index]);
+            }else
+                printf("No valid RPC variable found\n");
+            break;
+        }
+        if(i == (xbeeCount - 1)){
+            printf("No matching addresses found\n");
+        }
     }
     
-    if ( node != 0 ) {
-        while ( node->addrHigh != addrhigh){          
-            node = node->next;
+    
+    
+    
+    
+    
+    
+    /*if ( node != 0 ) {
+        printf("Comparing addrHigh %x to %x\n", node->addrHigh, addrHigh);
+        while ( node->addrHigh != addrHigh){
+            if(node->next != NULL){
+                node = node->next;
+            }else{
+                printf("Reached end of search with no addrHigh match\n");
+                break;
+            }
+            printf("Comparing addrHigh %x to %x\n", node->addrHigh, addrHigh);
         }
     
-        while(node->addrLow != addrlow){
-            node = node->next;
+        printf("Comparing addrLow %x to %x\n", node->addrLow, addrLow);
+        while(node->addrLow != addrLow){
+            if(node->next != NULL){
+                node = node->next;
+            }else{
+                printf("Reached end of search with no addrLow match\n");
+                break;
+            }
+            printf("Comparing addrLow %x to %x\n", node->addrLow, addrLow);
         }
     }else {
         printf("There is no node in the list");
     }
     
     if(node != 0 && index >= 0){
-        node->analogData[index] = analogInputFormat(data, node->analogType[index]);
+        //Place the analog data in the appropriate position in the struct
+        analogData = analogInputFormat(data, node->analogType[index]);
+        node->analogData[index] = analogData;
+        
+        if(node->analogRpcDataPointer[index] != NULL){
+            //Also push the analog data to the RPC variable
+            *node->analogRpcDataPointer[index] = analogData;
+            printf("Storing value %f into RPC pointer. Value stored is %f\n", analogData, *node->analogRpcDataPointer[index]);
+        }
     }
     else{
         printf("Node is not in the list");
+    }*/
+}
+
+
+
+
+void compareDigitalReadWrite(){
+    int mask = 1;
+    int i, digiIndex;
+    int rpcValue = 0;
+    int digiValue = 0;
+    
+    for(i = 0; i < xbeeCount; i++){ //Loop through all xbees
+        mask = 1;
+        
+        for(digiIndex = 0; digiIndex < 10; digiIndex++){    //Loop through all digital inputs to see if they do not match the corresponding RPC variable
+            
+            if(xbeeList[i].digitalType[digiIndex] == 1){    //Is this digital I/O a light control (digital output)?
+                
+                if(*xbeeList[i].digitalOutRpcDataPointer[digiIndex])
+                    rpcValue = 1;
+                else
+                    rpcValue = 0;
+                
+                if((xbeeList[i].digitalData & mask) != rpcValue){
+                    printf("Xbee%d: Digital output %d = %d doesn't match RPC variable = %d  Updating Xbee...\n", i, digiIndex, xbeeList[i].digitalData & mask, rpcValue);
+                    //This means that the digital output is in the incorrect state
+                    //Therefore write out the RPC state to the radio
+                    digitalWriteXbee(xbeeList[i].addrHigh, xbeeList[i].addrLow, digiIndex, rpcValue);
+                    //printf("Old digitalData = %d\t", xbeeList[i].digitalData);
+                    xbeeList[i].digitalData = (xbeeList[i].digitalData & ~mask) | (rpcValue << digiIndex); //Update the digitalData value with the new output value
+                    //printf("Updated digitalData = %d, mask = %d, rpcValue = %d, digiIndex = %d\n", xbeeList[i].digitalData, mask, rpcValue, digiIndex);
+                }
+                //Otherwise, it matches
+            }
+            
+            if(xbeeList[i].digitalType[digiIndex] == 2){    //Is this digital I/O a motion detector (digital input)?
+                digiValue = (xbeeList[i].digitalData & mask);
+                
+                //Get the RPC value
+                if(*xbeeList[i].digitalInRpcDataPointer[digiIndex])
+                    rpcValue = 1;
+                else
+                    rpcValue = 0;
+                    
+                if(digiValue != rpcValue){  //This means there has been a state change, either motion detected, or sensor returning to normal
+                    
+                    if(digiValue == 0 || rpcValue == 0){     //Motion detected
+                    
+//                        printf("Motion detected on Xbee%d\n", i);
+                        //if(digiValue)
+//                            rpcValue = 1;
+//                        else
+//                            rpcValue = 0;
+
+                        rpcValue = 1;
+                        *xbeeList[i].digitalInRpcDataPointer[digiIndex] = rpcValue;
+                    
+                        *xbeeList[i].digitalOutRpcDataPointer[0] = 1;   //Turn on the light
+                        xbeeList[i].timerList[digiIndex]->start();       //Restart timer
+                    }
+                }
+                
+            }
+            mask = mask << 1;
+        }
     }
-}
\ No newline at end of file
+}
+
+
+
+void monitorTimers(){
+
+    for(int i = 0; i < xbeeCount; i++){                             //Loop through  all xbees
+        for(int digiIndex = 0; digiIndex < 10; digiIndex++){        //Loop through all digital I/O
+            if(xbeeList[i].digitalType[digiIndex] == 2){            //See if I/O is a motion detector input
+                if(xbeeList[i].timerList[digiIndex]->read() > 15){   //Check if timer has expired
+                    *xbeeList[i].digitalOutRpcDataPointer[0] = 0;   //If timer has expired, turn light off
+                }
+            }
+        }
+    }
+}