How to control Philips hue light from Blynk app?

You should be doing the GET test first with String “/2” and the url not terminated with a backslash.

I have this on the wemos side

BLYNK_WRITE(V0)   // Webhook widget
{
  String webhookdata = param.asStr();
  //Serial.println("hue feedback:"); 
  Serial.println(webhookdata); 
}

BLYNK_WRITE(V1)  // button
{
  //lightBrightness = param.asInt();
  //String msgBody = ("{""\"bri\":" + String(lightBrightness) + "}");
  String msgBody = "/2";
  Serial.println(msgBody);
  Blynk.virtualWrite(V0, msgBody); // send to Webhook on V0  
}

And the webhook is on V0 with URL http://ip/user/api/lights/pin/ method GET, body empty. When I push the button in the app I indeed see /2, but nothing is returned

You have api and user the wrong way round in this url.

Human error after all…
GET works with http://ip/api/user/lights/pin/ BUT it needs {} in the body, with an empty body it gives an invalid json response.

I also changed V1 back to the slider (with a range of 10-255) and it works!

/*************************************************************
 WebhookPUTtest.ino by Costas the code 13/3/18 
 Control brightness of Philips Hue Light with Blynk Webhook widget on a local server only!
 V0 Webhook widget url syntax: http://<bridge ip address>/api/<username>/lights/<id>/state
    Method PUT
    Body /pin/   
 V1 Blynk slider with no decimal places set as send on release   
    range 10 to 255
 *************************************************************/

#define BLYNK_PRINT Serial
#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>

#define BLYNK_MAX_READBYTES 4096

char auth[] = "xxxxxxxxxxxxxxxxxxx";
char ssid[] = "xxxxxxxxxxxxxx";
char pass[] = "xxxxxxxxxxxxx";
#define server "192.168.0.201"
unsigned int lightBrightness = 10; // minimum brightness value for a white hue lamp

void setup()
{
  Serial.begin(115200);
  Blynk.begin(auth, ssid, pass, server, 8080);
  pinMode(LED_BUILTIN,OUTPUT);
  digitalWrite(LED_BUILTIN,LOW);
  Serial.println("Starting program...");
}

BLYNK_WRITE(V0)   // Webhook widget
{
  String webhookdata = param.asStr();
  Serial.println("hue feedback:"); 
  Serial.println(webhookdata); 
}

BLYNK_WRITE(V1)  // button
{
  lightBrightness = param.asInt();
  String msgBody = ("{""\"bri\":" + String(lightBrightness) + "}");
  Serial.println(msgBody);
  Blynk.virtualWrite(V0, msgBody); // send to Webhook on V0  
}

void loop()
{
  Blynk.run();
}

Thank you very much for helping with this problem!

1 Like

Knew we would get there in the end. I’ll add Philips Hue light hacker to my CV :slight_smile:

I find this very hard to believe as the GET doesn’t require a body as per the Philips API and all other GET methods. Probably just need to set content type as text/plain when using GET rather the json for PUT.

I just tried switching to text/plain and still get this error:

[{“error”:{“type”:2,“address”:“/lights/2”,“description”:“body contains invalid json”}}]

You will notice 2 appears twice in that response.

Something wrong with the formatting somewhere but probably not the body as GET doesn’t use it.

Might be that you ignore the Blynk warning, pretty sure I do, and use the double backslash in the url

as //pin/ and just send 2 to the Webhook rather than “/2”.

The Blynk error message is blatantly wrong as the url DOES start with the required http / https and at best it should say something like “badly formatted url” for double backslash. But I’m pretty sure you can ignore the error message and it’s best to use double backslash.

I believe the first 2 refers to the type of error the Hue Bridge is returning, type 1 is invalid user, type 2 is invalid json and type 3 I forgot…

I wrote an addition which adds an on/off button to the system, just need to figure a way of verifying whether the current slider position corresponds to the brightness of the light (Philips doesn’t allow brightness changes when the light is off).
Could also change the slider range to 0-255 and let everything below 10 send the off command, but then I need a smart way of sending the on command only once (Philips advises to not always send the on command with another command once the light is already on)

BLYNK_WRITE(V2)   //  on/off button
{
  if( param.asInt() == 1){
    lightState = "true";
  }
  else if ( param.asInt() == 0){
    lightState = "false";
  }
  String msgBody = ("{""\"on\":" + lightState + "}");
  Serial.println(msgBody);
  Blynk.virtualWrite(V0, msgBody); // send to Webhook on V0
}

Slider with off function:

BLYNK_WRITE(V1)  // slider with off function
{
  lightBrightness = param.asInt();
  if (lightBrightness < 10){
    lightState = "false, ";
  }
  else {
    lightState = "true, ";
  }
  String msgBody = ("{""\"on\":" + lightState + "\"bri\":" + String(lightBrightness) + "}");
  Serial.println(msgBody);
  Blynk.virtualWrite(V0, msgBody); // send to Webhook on V0  
}
1 Like

Comprehensive schedule of error messages at Login - Philips Hue Developer Program

My thoughts on the on / off with hue settings is to send both parts of the json via the slider.
We send 7 or 8 variables in some of our json strings.

I added this implementation to my previous post, works really nice! Now I can start thinking of ways to add multiple lights/scenes easily. This is where the hue app has an advantage I guess.

1 Like

@jbowser and @Costas: if I understand correctly, @jbowser wants to figure out how to control Hue lights using the Blynk app, via a suitable microcontroller. To be honest, I am too lazy to read through all of the message you exchanged. When I started to work with the Hues, it took me some time to find some good examples and to get it to work and maybe @jbowser is at the same stage. So what I can offer here is to paste some code that I am using and which works fine.

I have a number of Particle Photons and the user interface is either the Blynk app or hardware buttons/rotary encoders and the code on the microcontroller translates this into HTTP GET or PUT requests to read out or set the state (on or off, brightness level), respectively. I would like to point out that I don’t want to entirely take the credit for this code because it is adapted from different website that I found (e.g. by googling “particle photon philips hue PUT GET” or something like that).

A code example to read the state of a HUE group:

TCPClient HueHub; 
byte HueHubIP[] = { 192, 168, x, xx }; 
const char HueUsername[] = "2eoVQxxxxxxxxxxxxxxxxxxxxxxxxxxxx";  // Hue username
const int HueHubPort = 80;

boolean GetHue(int lightNum)  {
String jsonExtract;
  if (HueHub.connect(HueHubIP, HueHubPort))
  {
    HueHub.print("GET /api/");
    HueHub.print(HueUsername);
    HueHub.print("/lights/");
    HueHub.print(lightNum);  
    HueHub.println(" HTTP/1.1");
    HueHub.print("Host: ");
    HueHub.println(HueHubIP);
    HueHub.println("Content-type: application/json");
    HueHub.println("keep-alive");
    HueHub.println();
    while (HueHub.connected())
    {
      if (HueHub.available())
      {
        HueHub.findUntil("\"on\":", "\0");
        String jsonExtract = HueHub.readStringUntil(',');
        Serial.print("Reading Hue state feedback:...");
        Serial.println(jsonExtract);
        if (jsonExtract == "true") LightstripOn = true;
        if (jsonExtract == "false") LightstripOn = false;
        HueHub.findUntil("\"bri\":", "\0");
        Serial.print("Reading Hue brightness feedback:...");
        jsonExtract = HueHub.readStringUntil(',');
        Serial.println(jsonExtract);
        if (!LightstripOn) LightstripOn = 0; else LightStripHueBrightness = jsonExtract.toInt();  // set variable to brightness value
        BrightnessUpdated = true;   
        break;  // not capturing other light attributes yet
      }
    }
    HueHub.stop();
    return true;  // captured on,bri,hue
  }
  else
    return false;  // error reading on,bri,hue
}

The following code block can be used to set the state of a Hue, e.g. switch it on or off, set a brightness value.

boolean setHue(int lightNum,String command)  {
  if (HueHub.connect(HueHubIP, HueHubPort))  {
      HueHub.print("PUT /api/");
      HueHub.print(HueUsername);
      HueHub.print("/groups/");
      HueHub.print(lightNum);  // hueLight zero based, add 1
      HueHub.println("/action HTTP/1.1");
      HueHub.println("keep-alive");
      HueHub.print("Host: ");
      HueHub.println(HueHubIP);
      HueHub.print("Content-Length: ");
      HueHub.println(command.length());
      HueHub.println("Content-Type: text/plain;charset=UTF-8");
      HueHub.println();  // blank line before body
      HueHub.println(command);  // Hue command
      delay(30);
    HueHub.stop();
    return true;  // command executed
  }
  else {
     Serial.println(".. error: no connection to Hue bridge"); 
    return false;  // command failed
  }
}

The above routines can be simply called like in this example:

#define BathLightStripHue 14        
String HueOFF = "{\"on\": false}";
String Hue_SetBrightness = "{\"on\": true,\"bri\":";
String BathLightStripHueON = "{\"on\": true}";

To switch a light on and/or to set a certain brightness level:
int LightStripHueBrightness = 254;
setHue(BathLightStripHue,(Hue_SetBrightness+String(LightStripHueBrightness)+"}"));

Or to switch off:
setHue(BathLightStripHue, HueOFF);

Or to read the current state and brightness (this saves the brightness value and a boolean which holds state, i.e. on or off in two global variables):
GetHue(BathLightStripHue);

To implement a slider in the Blynk app, I did the following: (this simply reads the slide value and passes it on to the SetHue routine, in this case for the Hue group with nr 3)

String Hue_SetBrightness = "{\"on\": true,\"bri\":";

BLYNK_WRITE(HueVPin)  {                      // gets called from the slider widget on virtual pin "HueVPin"
  int HueBrightness  = param[0].asInt();
  setHue(3, Hue_SetBrightness + String(HueBrightness)+"}"));
}

Hope this helps.

1 Like

Should be easy with Node-RED + node-red-contrib-blynk-ws + node-red-contrib-node-hue ?

1 Like