Send JSON to Philips HUE

Hey Particle community,

I’m in the middle of a student project where I want to change the state of some Philip HUE lamps with our Particle Photon. I have some very basic understanding of coding and this project has proven difficult. I’m trying to adapt the code seen here: http://www.makeuseof.com/tag/control-philips-hue-lights-arduino-and-motion-sensor/

Since a lot of the code in that example is calling libraries that doesn’t exist on the Photon, I would be eternally grateful if someone could take the time to explain what I need to do to adapt it. We’re implementing the trigger to be a sound sensor, so the part that revolves around his motion sensor is abundant.

Here’s the code:

/*
    Talking to Hue from an Arduino
    By James Bruce (MakeUseOf.com)
    Adapted from code by Gilson Oguime. https://github.com/oguime/Hue_W5100_HT6P20B/blob/master/Hue_W5100_HT6P20B.ino
    
*/
#include <SPI.h>
#include <Ethernet.h>
 
//  Hue constants
 
const char hueHubIP[] = "192.168.1.216";  // Hue hub IP
const char hueUsername[] = "newdeveloper";  // Hue username
const int hueHubPort = 80;

// PIR
int pir = 2;
boolean activated = false;

//  Hue variables
boolean hueOn;  // on/off
int hueBri;  // brightness value
long hueHue;  // hue value
String hueCmd;  // Hue command

unsigned long buffer=0;  //buffer for received data storage
unsigned long addr;
 
//  Ethernet
 
byte mac[] = { 0x74,0x69,0x69,0x2D,0x30,0x31 };  // W5100 MAC address
IPAddress ip(192,168,1,2);  // Arduino IP
EthernetClient client;
/*
 
    Setup
 
*/
void setup()
{
  Serial.begin(9600);
  Ethernet.begin(mac,ip);

  pinMode(pir,INPUT);
  delay(2000);
  Serial.println("Ready.");
}

void loop() 
{
  if(digitalRead(pir) == 1){
    Serial.println("activated");
    
     // A series of four sample commands, which colour fades two lights between red and pink. Read up on the Hue API
    // documentation for more details on the exact commands to be used, but note that quote marks must be escaped.
    String command = "{\"on\": true,\"hue\": 50100,\"sat\":255,\"bri\":255,\"transitiontime\":"+String(random(15,25))+"}";
    setHue(1,command);
    command = "{\"on\": true,\"hue\": 65280,\"sat\":255,\"bri\":255,\"transitiontime\":"+String(random(15,25))+"}"; 
    setHue(2,command);
    command = "{\"hue\": 65280,\"sat\":255,\"bri\":255,\"transitiontime\":"+String(random(15,25))+"}";
    setHue(1,command);
    command = "{\"hue\": 50100,\"sat\":255,\"bri\":255,\"transitiontime\":"+String(random(15,25))+"}"; 
    setHue(2,command);
    
    // so we can track state
    activated = true;
  }
  else{
    
      activated = false;
      Serial.println("deactivated");
      
      //was activated, so send a single off command
      String command = "{\"on\": false}";
      setHue(1,command);
      setHue(2,command);
     
  }
  
}

/* setHue() is our main command function, which needs to be passed a light number and a 
 * properly formatted command string in JSON format (basically a Javascript style array of variables
 * and values. It then makes a simple HTTP PUT request to the Bridge at the IP specified at the start.
 */
boolean setHue(int lightNum,String command)
{
  if (client.connect(hueHubIP, hueHubPort))
  {
    while (client.connected())
    {
      client.print("PUT /api/");
      client.print(hueUsername);
      client.print("/lights/");
      client.print(lightNum);  // hueLight zero based, add 1
      client.println("/state HTTP/1.1");
      client.println("keep-alive");
      client.print("Host: ");
      client.println(hueHubIP);
      client.print("Content-Length: ");
      client.println(command.length());
      client.println("Content-Type: text/plain;charset=UTF-8");
      client.println();  // blank line before body
      client.println(command);  // Hue command
    }
    client.stop();
    return true;  // command executed
  }
  else
    return false;  // command failed
}

/* A helper function in case your logic depends on the current state of the light. 
 * This sets a number of global variables which you can check to find out if a light is currently on or not
 * and the hue etc. Not needed just to send out commands
 */
boolean getHue(int lightNum)
{
  if (client.connect(hueHubIP, hueHubPort))
  {
    client.print("GET /api/");
    client.print(hueUsername);
    client.print("/lights/");
    client.print(lightNum);  
    client.println(" HTTP/1.1");
    client.print("Host: ");
    client.println(hueHubIP);
    client.println("Content-type: application/json");
    client.println("keep-alive");
    client.println();
    while (client.connected())
    {
      if (client.available())
      {
        client.findUntil("\"on\":", "\0");
        hueOn = (client.readStringUntil(',') == "true");  // if light is on, set variable to true
 
        client.findUntil("\"bri\":", "\0");
        hueBri = client.readStringUntil(',').toInt();  // set variable to brightness value
 
        client.findUntil("\"hue\":", "\0");
        hueHue = client.readStringUntil(',').toInt();  // set variable to hue value
        
        break;  // not capturing other light attributes yet
      }
    }
    client.stop();
    return true;  // captured on,bri,hue
  }
  else
    return false;  // error reading on,bri,hue
}

To start with, you don’t need #include <SPI.h>, that’s already present in the framework and
there is no #include <Ethernet.h>, so this has to be replaced with some WiFi “drop-in” (like TCPClient instead of EthernetClient and the MAC setting will not be required)

2 Likes

there are examples here on connecting Particle to Hue… maybe you can shortcut your work by looking at the examples on the forum.

Thanks for the help. I had been Googlin’ like crazy for two days before posting here and I was quite desperate. Funnily I actually found some code that helped me on the right track about an hour after.

I still find the post that ScruffR did to be very helpful, so I thank you for that. Where can I read up on that stuff? Like the basics about how to communicate with the outside world using the Photon. I’m on a learning path here so any resources you recommend I read is appreciated.

Below is the code that I used incase anyone wonders into this post later on. I’ve left out usernames and stuff for obvious reasons. And this is my source: https://github.com/wasafiri/arce/blob/master/arce.ino

// Hue variables
TCPClient client;
const char hueHubIP[] = "your.ip.here";      // Local HUE bridge
const int hueHubPort = 80;                  // Local HUE bridge port
const char hueUsername[] = "your username here";  // HUE username
int lightNum;                               // Which HUE light we want to control
unsigned int len;                           // To store length of String command sent to HUE

void setup() {
    Serial.begin(9600);
    delay(200);
}

void loop() {
    Serial.println("*** FILTER BUBBLE DEACTIVATED. ***");
    String command = "{\"on\": true,\"hue\":56100,\"sat\":254,\"bri\":254,\"alert\":\"none\",\"transitiontime\":40}";
    setHue(lightNum, command);
    delay(9000);
        // Turning HUE off after alert produces nicer gradual off than by relying on 'else' to turn it off
    Serial.println("*** WARNING: FILTER BUBBLE ACTIVATED. ***");
    command = "{\"on\": true,\"hue\":46920,\"sat\":0,\"bri\":30,\"alert\":\"none\",\"transitiontime\":40}";
    setHue(lightNum, command);
    delay(9000);
}

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/yourusernamehere/lights/2/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("The HUE Bridge is not connected.");
    }
}
3 Likes