Home automation using Xbee radios
Dependencies: EthernetNetIf HTTPServer RPCInterface mbed C12832_lcd
Diff: main.cpp
- Revision:
- 9:4b1e3531dd00
- Parent:
- 8:e32fcca16102
- Child:
- 10:de0be690b3c0
--- 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 + } + } + } + } +}