Implement direct control for v2 protocol (Canvas and Shapes), clean up some formatting with v1 to match.
This commit is contained in:
parent
7276d254d6
commit
e61b6cd3d7
3 changed files with 107 additions and 46 deletions
|
|
@ -159,30 +159,77 @@ void NanoleafController::UpdateLEDs(std::vector<RGBColor>& colors)
|
|||
|
||||
if(model == NANOLEAF_LIGHT_PANELS_MODEL)
|
||||
{
|
||||
/*---------------------------------------------------------*\
|
||||
| Protocol V1 - https://forum.nanoleaf.me/docs |
|
||||
| |
|
||||
| Size Description |
|
||||
| --------------------------------------------------------- |
|
||||
| 1 nPanels Number of panels |
|
||||
| |
|
||||
| 1 panelId ID of panel |
|
||||
| 1 nFrames Number of frames (always 1) |
|
||||
| 1 R Red channel |
|
||||
| 1 G Green channel |
|
||||
| 1 B Blue channel |
|
||||
| 1 W White channel (ignored) |
|
||||
| 1 transitionTime Transition time (x 100ms) |
|
||||
\*---------------------------------------------------------*/
|
||||
uint8_t size = panel_ids.size();
|
||||
|
||||
uint8_t* message = (uint8_t*)malloc(size*7+6+1);
|
||||
uint8_t* message = (uint8_t*)malloc((size * 7) + 1);
|
||||
|
||||
message[0] = (uint8_t)size;
|
||||
message[0] = (uint8_t)size; /* nPanels */
|
||||
|
||||
for(int i = 0; i < size; i++)
|
||||
{
|
||||
message[( 7 * i) + 0 + 1] = (uint8_t)panel_ids[i];
|
||||
message[( 7 * i) + 1 + 1] = (uint8_t)1;
|
||||
message[( 7 * i) + 2 + 1] = (uint8_t)RGBGetRValue(colors[i]);
|
||||
message[( 7 * i) + 3 + 1] = (uint8_t)RGBGetGValue(colors[i]);
|
||||
message[( 7 * i) + 4 + 1] = (uint8_t)RGBGetBValue(colors[i]);
|
||||
message[( 7 * i) + 5 + 1] = (uint8_t)0;
|
||||
message[( 7 * i) + 6 + 1] = (uint8_t)0;
|
||||
message[(7 * i) + 0 + 1] = (uint8_t)panel_ids[i]; /* panelId */
|
||||
message[(7 * i) + 1 + 1] = (uint8_t)1; /* nFrames */
|
||||
message[(7 * i) + 2 + 1] = (uint8_t)RGBGetRValue(colors[i]); /* R */
|
||||
message[(7 * i) + 3 + 1] = (uint8_t)RGBGetGValue(colors[i]); /* G */
|
||||
message[(7 * i) + 4 + 1] = (uint8_t)RGBGetBValue(colors[i]); /* B */
|
||||
message[(7 * i) + 5 + 1] = (uint8_t)0; /* W */
|
||||
message[(7 * i) + 6 + 1] = (uint8_t)0; /* transitionTime */
|
||||
}
|
||||
|
||||
external_control_socket.udp_write(reinterpret_cast<char*>(message), size*7+6+1);
|
||||
external_control_socket.udp_write((char*)message, (size * 7) + 1);
|
||||
}
|
||||
else if(model == NANOLEAF_CANVAS_MODEL)
|
||||
else if((model == NANOLEAF_CANVAS_MODEL)
|
||||
|| (model == NANOLEAF_SHAPES_MODEL))
|
||||
{
|
||||
/*---------------------------------------------------------*\
|
||||
| Insert V2 protocol implementation here. |
|
||||
| Protocol V2 - https://forum.nanoleaf.me/docs |
|
||||
| |
|
||||
| Size Description |
|
||||
| --------------------------------------------------------- |
|
||||
| 2 nPanels Number of panels |
|
||||
| |
|
||||
| 2 panelId ID of panel |
|
||||
| 1 R Red channel |
|
||||
| 1 G Green channel |
|
||||
| 1 B Blue channel |
|
||||
| 1 W White channel (ignored) |
|
||||
| 2 transitionTime Transition time (x 100ms) |
|
||||
\*---------------------------------------------------------*/
|
||||
uint8_t size = panel_ids.size();
|
||||
|
||||
uint8_t* message = (uint8_t*)malloc((size * 8) + 2);
|
||||
|
||||
message[0] = (uint8_t)(size >> 8); /* nPanels H */
|
||||
message[1] = (uint8_t)(size & 0xFF); /* nPanels L */
|
||||
|
||||
for(int i = 0; i < size; i++)
|
||||
{
|
||||
message[(8 * i) + 0 + 2] = (uint8_t)(panel_ids[i] >> 8); /* panelId H */
|
||||
message[(8 * i) + 1 + 2] = (uint8_t)(panel_ids[i] & 0xFF); /* panelId L */
|
||||
message[(8 * i) + 2 + 2] = (uint8_t)RGBGetRValue(colors[i]); /* R */
|
||||
message[(8 * i) + 3 + 2] = (uint8_t)RGBGetGValue(colors[i]); /* G */
|
||||
message[(8 * i) + 4 + 2] = (uint8_t)RGBGetBValue(colors[i]); /* B */
|
||||
message[(8 * i) + 5 + 2] = (uint8_t)0; /* W */
|
||||
message[(8 * i) + 6 + 2] = (uint8_t)0; /* transitionTime H */
|
||||
message[(8 * i) + 7 + 2] = (uint8_t)0; /* transitionTime L */
|
||||
}
|
||||
|
||||
external_control_socket.udp_write((char *)message, (size * 8) + 2);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -192,21 +239,40 @@ void NanoleafController::StartExternalControl()
|
|||
request["write"]["command"] = "display";
|
||||
request["write"]["animType"] = "extControl";
|
||||
|
||||
/*-------------------------------------------------------------*\
|
||||
| Determine whether to use v1 or v2 extControl protocol based |
|
||||
| on model string |
|
||||
\*-------------------------------------------------------------*/
|
||||
if(model == NANOLEAF_LIGHT_PANELS_MODEL)
|
||||
{
|
||||
/*---------------------------------------------------------*\
|
||||
| Protocol v1 returns IP and port for UDP communication |
|
||||
\*---------------------------------------------------------*/
|
||||
request["write"]["extControlVersion"] = "v1";
|
||||
|
||||
json response;
|
||||
if((APIRequest("PUT", location, "/api/v1/"+auth_token+"/effects", &request, &response) / 100) == 2)
|
||||
{
|
||||
external_control_socket.udp_client(response["streamControlIpAddr"].get<std::string>().c_str(), std::to_string(response["streamControlPort"].get<int>()).c_str());
|
||||
|
||||
selectedEffect = NANOLEAF_DIRECT_MODE_EFFECT_NAME;
|
||||
}
|
||||
}
|
||||
else if(model == NANOLEAF_CANVAS_MODEL)
|
||||
else if((model == NANOLEAF_CANVAS_MODEL)
|
||||
|| (model == NANOLEAF_SHAPES_MODEL))
|
||||
{
|
||||
/*---------------------------------------------------------*\
|
||||
| Protocol v2 does not return anything, use device IP and |
|
||||
| port 60222 |
|
||||
\*---------------------------------------------------------*/
|
||||
request["write"]["extControlVersion"] = "v2";
|
||||
}
|
||||
|
||||
json response;
|
||||
if((APIRequest("PUT", location, "/api/v1/"+auth_token+"/effects", &request, &response) / 100) == 2)
|
||||
{
|
||||
external_control_socket.udp_client(response["streamControlIpAddr"].get<std::string>().c_str(), std::to_string(response["streamControlPort"].get<int>()).c_str());
|
||||
if((APIRequest("PUT", location, "/api/v1/"+auth_token+"/effects", &request) / 100) == 2)
|
||||
{
|
||||
external_control_socket.udp_client(address.c_str(), "60222");
|
||||
|
||||
selectedEffect = NANOLEAF_DIRECT_MODE_EFFECT_NAME;
|
||||
selectedEffect = NANOLEAF_DIRECT_MODE_EFFECT_NAME;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -280,4 +346,4 @@ std::string NanoleafController::GetSelectedEffect()
|
|||
int NanoleafController::GetBrightness()
|
||||
{
|
||||
return brightness;
|
||||
};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@
|
|||
#define NANOLEAF_DIRECT_MODE_EFFECT_NAME "*Dynamic*"
|
||||
#define NANOLEAF_LIGHT_PANELS_MODEL "NL22"
|
||||
#define NANOLEAF_CANVAS_MODEL "NL29"
|
||||
#define NANOLEAF_SHAPES_MODEL "NL42"
|
||||
|
||||
class NanoleafController
|
||||
{
|
||||
|
|
|
|||
|
|
@ -25,28 +25,25 @@ RGBController_Nanoleaf::RGBController_Nanoleaf(std::string a_address, int a_port
|
|||
type = DEVICE_TYPE_LIGHT;
|
||||
|
||||
/*-------------------------------------------------------------*\
|
||||
| Direct mode currently only supported for Nanoleaf Panels. |
|
||||
| Direct mode uses external control protocol. |
|
||||
\*-------------------------------------------------------------*/
|
||||
if(controller.GetModel() == NANOLEAF_LIGHT_PANELS_MODEL)
|
||||
{
|
||||
mode Direct;
|
||||
Direct.name = "Direct";
|
||||
Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR;
|
||||
Direct.color_mode = MODE_COLORS_PER_LED;
|
||||
modes.push_back(Direct);
|
||||
mode Direct;
|
||||
Direct.name = "Direct";
|
||||
Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR;
|
||||
Direct.color_mode = MODE_COLORS_PER_LED;
|
||||
modes.push_back(Direct);
|
||||
|
||||
/*---------------------------------------------------------*\
|
||||
| Set this effect as current if the name is selected. |
|
||||
\*---------------------------------------------------------*/
|
||||
if(controller.GetSelectedEffect() == NANOLEAF_DIRECT_MODE_EFFECT_NAME)
|
||||
{
|
||||
/*-----------------------------------------------------*\
|
||||
| If the direct mode is active, we need to call this |
|
||||
| method to open the socket. |
|
||||
\*-----------------------------------------------------*/
|
||||
controller.StartExternalControl();
|
||||
active_mode = 0;
|
||||
}
|
||||
/*---------------------------------------------------------*\
|
||||
| Set this effect as current if the name is selected. |
|
||||
\*---------------------------------------------------------*/
|
||||
if(controller.GetSelectedEffect() == NANOLEAF_DIRECT_MODE_EFFECT_NAME)
|
||||
{
|
||||
/*-----------------------------------------------------*\
|
||||
| If the direct mode is active, we need to call this |
|
||||
| method to open the socket. |
|
||||
\*-----------------------------------------------------*/
|
||||
controller.StartExternalControl();
|
||||
active_mode = 0;
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------*\
|
||||
|
|
@ -89,7 +86,7 @@ void RGBController_Nanoleaf::SetupZones()
|
|||
for(std::vector<int>::const_iterator it = controller.GetPanelIds().begin(); it != controller.GetPanelIds().end(); ++it)
|
||||
{
|
||||
led new_led;
|
||||
new_led.name = std::to_string(*it);
|
||||
new_led.name = std::to_string(*it);
|
||||
leds.push_back(new_led);
|
||||
}
|
||||
|
||||
|
|
@ -107,10 +104,7 @@ void RGBController_Nanoleaf::ResizeZone(int /*zone*/, int /*new_size*/)
|
|||
|
||||
void RGBController_Nanoleaf::DeviceUpdateLEDs()
|
||||
{
|
||||
if(controller.GetModel() == NANOLEAF_LIGHT_PANELS_MODEL)
|
||||
{
|
||||
controller.UpdateLEDs(colors);
|
||||
}
|
||||
controller.UpdateLEDs(colors);
|
||||
}
|
||||
|
||||
void RGBController_Nanoleaf::UpdateZoneLEDs(int /*zone*/)
|
||||
|
|
@ -133,7 +127,7 @@ void RGBController_Nanoleaf::DeviceUpdateMode()
|
|||
/*---------------------------------------------------------*\
|
||||
| Mode 0 is reserved for Direct mode |
|
||||
\*---------------------------------------------------------*/
|
||||
if(active_mode == 0 && controller.GetModel() == NANOLEAF_LIGHT_PANELS_MODEL)
|
||||
if(active_mode == 0)
|
||||
{
|
||||
controller.StartExternalControl();
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue