-
Notifications
You must be signed in to change notification settings - Fork 186
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix Philips Hue and clean up code #2109
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -119,7 +119,9 @@ bool PhilipsHueDevice::configure(std::unordered_map<string, string> settings) | |
if (username != "") | ||
{ | ||
sp::io::http::Request http(ip_address,port); | ||
auto response = http.get(string{ "/api/" } + username + "/lights"); | ||
string lightsListAPI = "/api/" + username + "/lights"; | ||
auto response = http.get(lightsListAPI); | ||
|
||
if (response.status != 200) // !OK | ||
{ | ||
LOG(WARNING) << "Failed to validate username on philips hue bridge: " << response.status; | ||
|
@@ -146,7 +148,7 @@ bool PhilipsHueDevice::configure(std::unordered_map<string, string> settings) | |
for (const auto& entry : hue_json.items()) | ||
{ | ||
auto currentInt = string(entry.key()).toInt(); | ||
LOG(DEBUG) << "Got key from Hue API " << currentInt; | ||
LOG(INFO) << "Got key from Hue API " << currentInt; | ||
if (currentInt >= light_count) light_count = currentInt; | ||
} | ||
|
||
|
@@ -201,37 +203,49 @@ int PhilipsHueDevice::getChannelCount() | |
|
||
void PhilipsHueDevice::updateLoop() | ||
{ | ||
sp::io::http::Request http(ip_address,port); | ||
|
||
while(run_thread) | ||
{ | ||
for(int n=0; n<light_count; n++) | ||
{ | ||
if (lights[n].dirty) | ||
LightInfo info = lights[n]; | ||
// Hue API can only handle about 10 requests per second | ||
std::this_thread::sleep_for(std::chrono::milliseconds(100)); | ||
if (info.laststate != "sat-" + string(info.saturation) + "-bri-" + string(info.brightness) + "-hue-" + string(info.hue) + "-transition-" + string(info.transitiontime)) | ||
{ | ||
LightInfo info; | ||
{ | ||
std::lock_guard<std::mutex> lock(mutex); | ||
lights[n].dirty = false; | ||
info = lights[n]; | ||
} | ||
string post_data; | ||
if (info.laststate != "sat-" + string(info.saturation) + "-bri-" + string(info.brightness) + "-hue-" + string(info.hue) + "-transition-" + string(info.transitiontime)) | ||
{ | ||
lights[n].laststate = "sat-" + string(info.saturation) + "-bri-" + string(info.brightness) + "-hue-" + string(info.hue) + "-transition-" + string(info.transitiontime); | ||
if (info.brightness > 0) | ||
post_data = "{\"on\":true, \"sat\":"+string(info.saturation)+", \"bri\":"+string(info.brightness)+",\"hue\":"+string(info.hue)+", \"transitiontime\": "+string(info.transitiontime)+"}"; | ||
else | ||
post_data = "{\"on\":false, \"transitiontime\": "+string(info.transitiontime)+"}"; | ||
auto response = http.request("put", string{ "/api/" } + username + "/lights/" + string(n + 1) + "/state", post_data); | ||
if (response.status != 200) // !OK | ||
{ | ||
LOG(WARNING) << "Failed to set light [" << (n + 1) << "] philips hue bridge: " << response.status; | ||
LOG(WARNING) << response.body; | ||
} | ||
} | ||
} | ||
} | ||
std::this_thread::sleep_for(std::chrono::milliseconds(50)); | ||
lights[n].dirty = true; | ||
} | ||
|
||
if (lights[n].dirty) | ||
{ | ||
sp::io::http::Request setLights(ip_address, port); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. By re-creating the sp::io::http::Request for each call, it makes a new tcp connection per call. If you reuse the same object it should keep a single connection open, which is better for performance. Did you run into some kind of bug why you needed to move this? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, that is actually what sent me down this whole rabbit hole... it would sometimes work for the first light, but not additional lights. Wireshark packet captures showed that after the first light call, it would malform all the subsequent calls, putting the json payload before the api call. Like: {"on":true, "sat":254, "bri":254,"hue":19660, "transitiontime": 1}put /api//lights/3/state instead of (when Wireshark capturing Postman): {"on": true, "bri": 254, "transitiontime": 1} So I pulled it out to make a separate connection each time and that did the trick, no more malformed API packets after that. I'm not sure why that is the case, I was on a bit of a time crunch when I was working on it (had a game scheduled) so I was certainly in "just make it work" mode. I don't know how many people even use the Hue feature, I just happen to already have them in my game space so might as well. I'll tinker with and clean it up some more but I can't promise any kind of timeline for it, so feel free to reject for now if you'd like and I can open a new PR if I make it any better. |
||
string APIEndpoint = "/api/" + username + "/lights/" + string(n+1) + "/state"; | ||
LightInfo currentLight = lights[n]; | ||
string postData; | ||
if (currentLight.brightness > 0) //light is on | ||
{ | ||
postData = "{\"on\":true, \"sat\":" + string(currentLight.saturation) + ", \"bri\":" + string(currentLight.brightness) + ", \"hue\":" + string(currentLight.hue) + ", \"transitiontime\":" + string(currentLight.transitiontime) + "}"; | ||
} | ||
else | ||
{ | ||
postData = "{\"on\":false}"; | ||
} | ||
|
||
// call the API | ||
auto resp = setLights.request("PUT", APIEndpoint, postData); | ||
if (resp.status == 200) // OK | ||
{ | ||
lights[n].dirty = false; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. By moving this here, and removing the lock, you created a race condition, which is likely why you needed the 2nd |
||
} | ||
else | ||
{ | ||
// Do nothing but keep the light flagged for future try | ||
} | ||
} | ||
else | ||
{ | ||
// Do nothing, the light is correct already | ||
} | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
tabs vs spaces. Please use 4 spaces instead of tabs.