Flashing Philips HUE bulbs & sending a SMS text message

Thanks to feedback from those on IRC who took time to give feedback on a project I’m currently working on to hook up my intercom to a Photon. My goal is to use the Photon to send a SMS text + give me visual notification through my Philips HUE bulbs when someone buzzes the intercom.

The code I’ve developed currently works with a pushbutton on a breadboard. I haven’t taken the step of hooking up the Photon to the intercom yet, but will update when I get there.

For the text messaging functionality, I’m using a Webhook (docs at docs.Particle.io). Right now I use Twilio but have Plivo implementation on my list as well.

Sharing the code here for feedback and/or critique. There are two versions – one that uses software debouncing and one that uses interrupts. Both work well with the pushbutton.

And hopefully this code can help others who are new to this – like me – get started!

First, the version using software debouncing. I have it up on my Github at https://github.com/wasafiri/arce

// Hue variables
TCPClient client;
const char hueHubIP[] = "192.168.1.16";     // local HUE bridge
const int hueHubPort = 80;                  // local HUE bridge port
const char hueUsername[] = "newdeveloper";  // hue username
int lightNum;                               // which HUE light we want to control
unsigned int len;                           // to store length of String command sent to HUE

// read the buzzer value
int buzzerPin = D3;                         // pin the buzzer is connected to
int buzzerState;                            // current reading from the input pin

// debouncing variables to check button twice before doing anything
long lastDebounceTime = 0;                  // the last time the output pin was toggled
long debounceDelay = 120;                   // the debounce time; increase if multiple texts are sent
int lastBuzzerState = HIGH;                 // store the previous reading from the buzzerPin

// Hue variables
TCPClient client;
const char hueHubIP[] = "192.168.1.16";     // local HUE bridge
const int hueHubPort = 80;                  // local HUE bridge port
const char hueUsername[] = "newdeveloper";  // hue username
int lightNum;                               // which HUE light we want to control
unsigned int len;                           // to store length of String command sent to HUE

// read the buzzer value
int buzzerPin = D3;                         // pin the buzzer is connected to
int buzzerState;                            // current reading from the input pin

// debouncing variables to check button twice before doing anything
long lastDebounceTime = 0;                  // the last time the output pin was toggled
long debounceDelay = 120;                   // the debounce time; increase if multiple texts are sent
int lastBuzzerState = HIGH;                 // store the previous reading from the buzzerPin

void setup() {
    // read buzzerPin
    pinMode(buzzerPin, INPUT_PULLUP);
    
    // turn on serial communication
    Serial.begin(9600);
    delay(200);
}

void loop() {
    // put the state of the switch into a local variable, 'reading':
    int reading = digitalRead(buzzerPin);
    
    // check to see if the buzzer has went off
    // (i.e. the input went from LOW to HIGH),  and you've waited
    // long enough to ignore any noise:
    if (reading != lastBuzzerState) {
        // reset the debouncing timer
        lastDebounceTime = millis();
    }
    
    // whatever the reading is at, it's been there for longer
    // than the debounce delay, so take it as the actual current state:
    if ((millis() - lastDebounceTime) > debounceDelay) {
        
        // change saved buzzer state to buzzerState variable
        if (reading != buzzerState) {
            buzzerState = reading;
            
            // if the buzzerState is LOW, send a text via Twilio    
            if (buzzerState == LOW) {
                Serial.print(buzzerState);
                // use a webhook to send json to Twilio
                Particle.publish("twilio", "Heads up: Someone just buzzed your intercom!", 60, PRIVATE);
            
                // if a connection to the HUE bridge exists then do stuff with the lights
                String command = "{\"on\": true,\"hue\":50000,\"sat\":254,\"bri\":180,\"alert\":\"none\",\"transitiontime\":40}";
                setHue(lightNum, command);
                delay(12000);
                // turning HUE off after alert produces nicer gradual off than by relying on 'else' to turn it off
                command = "{\"on\": false}";
                setHue(lightNum, command);
                delay(50);
            }
        }
        else {
            // turn HUE off if for some reason it's on, else it will stay on until someone pushes the buzzer
            String command = "{\"on\": false}";
            setHue(lightNum, command);
        }
    }
    // Revert buzzer state 
    lastBuzzerState = reading;
}

boolean setHue(int lightNum, String command) {      // moving this out of the loop
    if (client.connect(hueHubIP, hueHubPort)) {
        unsigned int len = command.length();        // get length
        client.println("PUT /api/newdeveloper/lights/3/state HTTP/1.1");
        client.println("Connection: keep-alive");
        client.print("Host: ");
        client.println(hueHubIP);
        client.println("Content-Type: text/plain;charset=UTF-8");
        client.print("Content-Length: ");
        client.println(len);                        // brightness string + val length
        client.println();                           // blank line before body
        client.print(command);
        delay(100);                                 // slight delay IMPORTANT
        client.stop();
    }
    else {
        Serial.println("hue bridge not connected");
    }
}

The version using interrupts:

// Hue variables
TCPClient client;
const char hueHubIP[] = "192.168.1.16";     // local HUE bridge
const int hueHubPort = 80;                  // local HUE bridge port
const char hueUsername[] = "newdeveloper";  // hue username
int lightNum;                               // which HUE light we want to control
unsigned int len;                           // to store length of String command sent to HUE

// read the buzzer value
int buzzerPin = D3;                         // pin the buzzer is connected to
int buzzerState;                            // current reading from the input pin

// debouncing variables to check button twice before doing anything
long lastDebounceTime = 0;                  // the last time the output pin was toggled
long debounceDelay = 120;                   // the debounce time; increase if multiple texts are sent
bool buttonWasPressed = false;

void setup() {
    // read buzzerPin
    pinMode(buzzerPin, INPUT_PULLUP);
    attachInterrupt(D3, interrupt, FALLING);
    
    // turn on serial communication
    Serial.begin(9600);
    delay(200);
}

void interrupt() {
    if ((millis() - lastDebounceTime) > debounceDelay) {
        buttonWasPressed = true;
    }
}

void loop() {
    // if the button was pressed, send a text via Twilio + do stuff with the lights
    if (buttonWasPressed == true) {

        String command = "{\"on\": true,\"hue\":50000,\"sat\":254,\"bri\":180,\"alert\":\"none\",\"transitiontime\":40}";
        setHue(lightNum, command);
        delay(10000);
        // turning HUE off after alert produces nicer gradual off than by relying on 'else' to turn it off
        command = "{\"on\": false}";
        setHue(lightNum, command);
        Serial.println("command sent to HUE ");     // command executed
        
        // use a webhook to send json to Twilio
        Particle.publish("twilio", "Heads up: Someone just buzzed your intercom!", 60, PRIVATE);
        delay(20);
        buttonWasPressed = false;
    }
    else {
        // turn HUE off if for some reason it's on, else it will stay on until someone pushes the buzzer
        String command = "{\"on\": false}";
        setHue(lightNum, command);
    }
}

boolean setHue(int lightNum, String command) {      // moving this out of the loop
    if (client.connect(hueHubIP, hueHubPort)) {
        unsigned int len = command.length();        // get length
        client.println("PUT /api/newdeveloper/lights/3/state HTTP/1.1");
        client.println("Connection: keep-alive");
        client.print("Host: ");
        client.println(hueHubIP);
        client.println("Content-Type: text/plain;charset=UTF-8");
        client.print("Content-Length: ");
        client.println(len);                        // brightness string + val length
        client.println();                           // blank line before body
        client.print(command);
        delay(100);                                 // slight delay IMPORTANT
        client.stop();
    }
    else {
        Serial.println("hue bridge not connected");
    }
}
2 Likes