Add support for the custom colorXY trait

This adds color support to the virtual light
Change-Id: Iff26f08d8852b8d6465eed2fa3e7ba1471c9bcb2
Reviewed-on: https://weave-review.googlesource.com/1528
Reviewed-by: Paul Westbrook <pwestbro@google.com>
diff --git a/examples/daemon/light/light.cc b/examples/daemon/light/light.cc
index 484b9e1..d54de93 100644
--- a/examples/daemon/light/light.cc
+++ b/examples/daemon/light/light.cc
@@ -19,12 +19,44 @@
 
     device->AddStateDefinitionsFromJson(R"({
       "onOff": {"state": ["on", "standby"]},
-      "brightness": {"brightness": "integer"}
+      "brightness": {"brightness": "integer"},
+      "colorXY": {
+        "colorSetting": {
+          "properties": {
+            "colorX": {"minimum": 0.0, "maximum": 1.0},
+            "colorY": {"minimum": 0.0, "maximum": 1.0}
+          }
+        },
+        "colorCapRed": {
+          "properties": {
+            "colorX": {"minimum": 0.0, "maximum": 1.0},
+            "colorY": {"minimum": 0.0, "maximum": 1.0}
+          }
+        },
+        "colorCapGreen": {
+          "properties": {
+            "colorX": {"minimum": 0.0, "maximum": 1.0},
+            "colorY": {"minimum": 0.0, "maximum": 1.0}
+          }
+        },
+        "colorCapBlue": {
+          "properties": {
+            "colorX": {"minimum": 0.0, "maximum": 1.0},
+            "colorY": {"minimum": 0.0, "maximum": 1.0}
+          }
+        }
+      }
     })");
 
     device->SetStatePropertiesFromJson(R"({
       "onOff":{"state": "standby"},
-      "brightness":{"brightness": 0}
+      "brightness":{"brightness": 0},
+      "colorXY": {
+        "colorSetting": {"colorX": 0, "colorY": 0},
+        "colorCapRed":  {"colorX": 0.674, "colorY": 0.322},
+        "colorCapGreen":{"colorX": 0.408, "colorY": 0.517},
+        "colorCapBlue": {"colorX": 0.168, "colorY": 0.041}
+      }
     })",
                                        nullptr);
 
@@ -46,6 +78,28 @@
              }
            }
         }
+      },
+      "_colorXY": {
+        "_setConfig": {
+          "minimalRole": "user",
+          "parameters": {
+            "_colorSetting": {
+              "type": "object",
+              "properties": {
+                "_colorX": {
+                  "type": "number",
+                  "minimum": 0,
+                  "maximum": 1
+                },
+                "_colorY": {
+                  "type": "number",
+                  "minimum": 0,
+                  "maximum": 1
+                }
+              }
+            }
+          }
+        }
       }
     })");
     device->AddCommandHandler("onOff.setConfig",
@@ -54,6 +108,9 @@
     device->AddCommandHandler("brightness.setConfig",
                               base::Bind(&LightHandler::OnBrightnessSetConfig,
                                          weak_ptr_factory_.GetWeakPtr()));
+    device->AddCommandHandler("_colorXY._setConfig",
+                              base::Bind(&LightHandler::OnColorXYSetConfig,
+                                         weak_ptr_factory_.GetWeakPtr()));
   }
 
  private:
@@ -105,11 +162,51 @@
     cmd->Abort(error.get(), nullptr);
   }
 
+  void OnColorXYSetConfig(const std::weak_ptr<weave::Command>& command) {
+    auto cmd = command.lock();
+    if (!cmd)
+      return;
+    LOG(INFO) << "received command: " << cmd->GetName();
+    auto params = cmd->GetParameters();
+    base::DictionaryValue* colorXY = nullptr;
+    if (params->GetDictionary("_colorSetting", &colorXY)) {
+      bool updateState = false;
+      double X = 0.0;
+      double Y = 0.0;
+      if (colorXY->GetDouble("_colorX", &X)) {
+        color_X_ = X;
+        updateState = true;
+      }
+
+      if (colorXY->GetDouble("_colorY", &Y)) {
+        color_Y_ = Y;
+        updateState = true;
+      }
+
+      if (updateState)
+        UpdateLightState();
+
+      cmd->Complete({}, nullptr);
+      return;
+    }
+
+    weave::ErrorPtr error;
+    weave::Error::AddTo(&error, FROM_HERE, "example", "invalid_parameter_value",
+                        "Invalid parameters");
+    cmd->Abort(error.get(), nullptr);
+  }
+
   void UpdateLightState() {
     base::DictionaryValue state;
     state.SetString("onOff.state", light_status_ ? "on" : "standby");
     state.SetInteger("brightness.brightness", brightness_state_);
+
+    std::unique_ptr<base::DictionaryValue> colorXY(new base::DictionaryValue());
+    colorXY->SetDouble("colorX", color_X_);
+    colorXY->SetDouble("colorY", color_Y_);
+    state.Set("colorXY.colorSetting", colorXY.get());
     device_->SetStateProperties(state, nullptr);
+    colorXY.release();
   }
 
   weave::Device* device_{nullptr};
@@ -117,6 +214,8 @@
   // Simulate the state of the light.
   bool light_status_;
   int32_t brightness_state_;
+  double color_X_{0.0};
+  double color_Y_{0.0};
   base::WeakPtrFactory<LightHandler> weak_ptr_factory_{this};
 };