1c18c7cfe350a5e671deaf1c2eaa30868e6ceb67fPaul Westbrook// Copyright 2015 The Weave Authors. All rights reserved.
2c18c7cfe350a5e671deaf1c2eaa30868e6ceb67fPaul Westbrook// Use of this source code is governed by a BSD-style license that can be
3c18c7cfe350a5e671deaf1c2eaa30868e6ceb67fPaul Westbrook// found in the LICENSE file.
4c18c7cfe350a5e671deaf1c2eaa30868e6ceb67fPaul Westbrook
53fb474e64c9ed199919313321e46da3a531ecc7dJohan Euphrosine#include "examples/daemon/common/daemon.h"
63fb474e64c9ed199919313321e46da3a531ecc7dJohan Euphrosine
7c18c7cfe350a5e671deaf1c2eaa30868e6ceb67fPaul Westbrook#include <weave/device.h>
8c18c7cfe350a5e671deaf1c2eaa30868e6ceb67fPaul Westbrook
9c18c7cfe350a5e671deaf1c2eaa30868e6ceb67fPaul Westbrook#include <base/bind.h>
10c18c7cfe350a5e671deaf1c2eaa30868e6ceb67fPaul Westbrook#include <base/memory/weak_ptr.h>
11c18c7cfe350a5e671deaf1c2eaa30868e6ceb67fPaul Westbrook
12d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenkonamespace {
13c18c7cfe350a5e671deaf1c2eaa30868e6ceb67fPaul Westbrook
14d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenkoconst char kTraits[] = R"({
15d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko  "onOff": {
16d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko    "commands": {
17d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko      "setConfig": {
18d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko        "minimalRole": "user",
19d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko        "parameters": {
20d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko          "state": {
21d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko            "type": "string",
22d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko            "enum": [ "on", "standby" ]
2303cd192eceb46f936ad89e6ae04dac130202e18cPaul Westbrook          }
24d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko        }
25d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko      }
26d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko    },
27d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko    "state": {
28d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko      "state": {
29d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko        "type": "string",
308d0cfefae24985025a934ea5461a51472c59cfc0Alex Vakulenko        "enum": [ "on", "standby" ],
318d0cfefae24985025a934ea5461a51472c59cfc0Alex Vakulenko        "isRequired": true
32d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko      }
33d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko    }
34d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko  },
35d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko  "brightness": {
36d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko    "commands": {
37d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko      "setConfig": {
38d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko        "minimalRole": "user",
39d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko        "parameters": {
40d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko          "brightness": {
41d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko            "type": "integer",
42d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko            "minimum": 0,
43d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko            "maximum": 100
4403cd192eceb46f936ad89e6ae04dac130202e18cPaul Westbrook          }
4503cd192eceb46f936ad89e6ae04dac130202e18cPaul Westbrook        }
4603cd192eceb46f936ad89e6ae04dac130202e18cPaul Westbrook      }
47d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko    },
488d0cfefae24985025a934ea5461a51472c59cfc0Alex Vakulenko    "state": {
498d0cfefae24985025a934ea5461a51472c59cfc0Alex Vakulenko      "brightness": {
508d0cfefae24985025a934ea5461a51472c59cfc0Alex Vakulenko        "type": "integer",
518d0cfefae24985025a934ea5461a51472c59cfc0Alex Vakulenko        "isRequired": true,
528d0cfefae24985025a934ea5461a51472c59cfc0Alex Vakulenko        "minimum": 0,
538d0cfefae24985025a934ea5461a51472c59cfc0Alex Vakulenko        "maximum": 100
548d0cfefae24985025a934ea5461a51472c59cfc0Alex Vakulenko      }
558d0cfefae24985025a934ea5461a51472c59cfc0Alex Vakulenko    }
56d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko  },
57d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko  "colorXY": {
58d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko    "commands": {
59d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko      "setConfig": {
60d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko        "minimalRole": "user",
61d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko        "parameters": {
62d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko          "colorSetting": {
63d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko            "type": "object",
64d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko            "required": [
65d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko              "colorX",
66d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko              "colorY"
67d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko            ],
68d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko            "properties": {
69d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko              "colorX": {
70d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko                "type": "number",
71d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko                "minimum": 0.0,
72d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko                "maximum": 1.0
73d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko              },
74d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko              "colorY": {
75d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko                "type": "number",
76d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko                "minimum": 0.0,
77d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko                "maximum": 1.0
78d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko              }
79d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko            },
80d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko            "additionalProperties": false
81d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko          }
828d0cfefae24985025a934ea5461a51472c59cfc0Alex Vakulenko        },
838d0cfefae24985025a934ea5461a51472c59cfc0Alex Vakulenko        "errors": ["colorOutOfRange"]
8403cd192eceb46f936ad89e6ae04dac130202e18cPaul Westbrook      }
85d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko    },
86d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko    "state": {
87d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko      "colorSetting": {
888d0cfefae24985025a934ea5461a51472c59cfc0Alex Vakulenko        "type": "object",
898d0cfefae24985025a934ea5461a51472c59cfc0Alex Vakulenko        "isRequired": true,
908d0cfefae24985025a934ea5461a51472c59cfc0Alex Vakulenko        "required": [ "colorX", "colorY" ],
91d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko        "properties": {
92d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko          "colorX": {
93d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko            "type": "number",
94d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko            "minimum": 0.0,
95d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko            "maximum": 1.0
96d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko          },
97d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko          "colorY": {
98d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko            "type": "number",
99d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko            "minimum": 0.0,
100d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko            "maximum": 1.0
10142b0a7b1235eb029f9f678dd54076d7b6b0c5a70Alex Vakulenko          }
10242b0a7b1235eb029f9f678dd54076d7b6b0c5a70Alex Vakulenko        }
10342b0a7b1235eb029f9f678dd54076d7b6b0c5a70Alex Vakulenko      },
104d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko      "colorCapRed": {
1058d0cfefae24985025a934ea5461a51472c59cfc0Alex Vakulenko        "type": "object",
1068d0cfefae24985025a934ea5461a51472c59cfc0Alex Vakulenko        "isRequired": true,
1078d0cfefae24985025a934ea5461a51472c59cfc0Alex Vakulenko        "required": [ "colorX", "colorY" ],
108d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko        "properties": {
109d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko          "colorX": {
110d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko            "type": "number",
111d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko            "minimum": 0.0,
112d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko            "maximum": 1.0
113d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko          },
114d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko          "colorY": {
115d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko            "type": "number",
116d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko            "minimum": 0.0,
117d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko            "maximum": 1.0
11842b0a7b1235eb029f9f678dd54076d7b6b0c5a70Alex Vakulenko          }
119c18c7cfe350a5e671deaf1c2eaa30868e6ceb67fPaul Westbrook        }
12003cd192eceb46f936ad89e6ae04dac130202e18cPaul Westbrook      },
121d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko      "colorCapGreen": {
1228d0cfefae24985025a934ea5461a51472c59cfc0Alex Vakulenko        "type": "object",
1238d0cfefae24985025a934ea5461a51472c59cfc0Alex Vakulenko        "isRequired": true,
1248d0cfefae24985025a934ea5461a51472c59cfc0Alex Vakulenko        "required": [ "colorX", "colorY" ],
125d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko        "properties": {
126d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko          "colorX": {
127d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko            "type": "number",
128d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko            "minimum": 0.0,
129d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko            "maximum": 1.0
130d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko          },
131d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko          "colorY": {
132d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko            "type": "number",
133d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko            "minimum": 0.0,
134d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko            "maximum": 1.0
135d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko          }
136d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko        }
137d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko      },
138d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko      "colorCapBlue": {
1398d0cfefae24985025a934ea5461a51472c59cfc0Alex Vakulenko        "type": "object",
1408d0cfefae24985025a934ea5461a51472c59cfc0Alex Vakulenko        "isRequired": true,
1418d0cfefae24985025a934ea5461a51472c59cfc0Alex Vakulenko        "required": [ "colorX", "colorY" ],
142d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko        "properties": {
143d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko          "colorX": {
144d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko            "type": "number",
145d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko            "minimum": 0.0,
146d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko            "maximum": 1.0
147d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko          },
148d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko          "colorY": {
149d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko            "type": "number",
150d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko            "minimum": 0.0,
151d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko            "maximum": 1.0
15203cd192eceb46f936ad89e6ae04dac130202e18cPaul Westbrook          }
15303cd192eceb46f936ad89e6ae04dac130202e18cPaul Westbrook        }
154c18c7cfe350a5e671deaf1c2eaa30868e6ceb67fPaul Westbrook      }
155d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko    }
156d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko  }
157d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko})";
158d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko
159d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenkoconst char kDefaultState[] = R"({
160d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko  "colorXY": {
161d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko    "colorSetting": {"colorX": 0, "colorY": 0},
162d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko    "colorCapRed":  {"colorX": 0.674, "colorY": 0.322},
163d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko    "colorCapGreen":{"colorX": 0.408, "colorY": 0.517},
164d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko    "colorCapBlue": {"colorX": 0.168, "colorY": 0.041}
165d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko  }
166d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko})";
167d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko
168d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenkoconst char kComponent[] = "light";
169d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko
170d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko}  // anonymous namespace
171d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko
172d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko// LightHandler is a command handler example that shows
173d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko// how to handle commands for a Weave light.
174d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenkoclass LightHandler {
175d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko public:
176d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko  LightHandler() = default;
177d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko  void Register(weave::Device* device) {
178d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko    device_ = device;
179d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko
180d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko    device->AddTraitDefinitionsFromJson(kTraits);
181d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko    CHECK(device->AddComponent(kComponent, {"onOff", "brightness", "colorXY"},
182d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko                               nullptr));
18334668e731bb194b443bc0e6029d6d3583f08de28Vitaly Buka    CHECK(
18434668e731bb194b443bc0e6029d6d3583f08de28Vitaly Buka        device->SetStatePropertiesFromJson(kComponent, kDefaultState, nullptr));
185d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko    UpdateLightState();
186d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko
187d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko    device->AddCommandHandler(kComponent, "onOff.setConfig",
1883fb474e64c9ed199919313321e46da3a531ecc7dJohan Euphrosine                              base::Bind(&LightHandler::OnOnOffSetConfig,
1893fb474e64c9ed199919313321e46da3a531ecc7dJohan Euphrosine                                         weak_ptr_factory_.GetWeakPtr()));
190d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko    device->AddCommandHandler(kComponent, "brightness.setConfig",
1913fb474e64c9ed199919313321e46da3a531ecc7dJohan Euphrosine                              base::Bind(&LightHandler::OnBrightnessSetConfig,
1923fb474e64c9ed199919313321e46da3a531ecc7dJohan Euphrosine                                         weak_ptr_factory_.GetWeakPtr()));
193d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko    device->AddCommandHandler(kComponent, "colorXY.setConfig",
19403cd192eceb46f936ad89e6ae04dac130202e18cPaul Westbrook                              base::Bind(&LightHandler::OnColorXYSetConfig,
19503cd192eceb46f936ad89e6ae04dac130202e18cPaul Westbrook                                         weak_ptr_factory_.GetWeakPtr()));
196c18c7cfe350a5e671deaf1c2eaa30868e6ceb67fPaul Westbrook  }
197c18c7cfe350a5e671deaf1c2eaa30868e6ceb67fPaul Westbrook
198c18c7cfe350a5e671deaf1c2eaa30868e6ceb67fPaul Westbrook private:
1993fb474e64c9ed199919313321e46da3a531ecc7dJohan Euphrosine  void OnBrightnessSetConfig(const std::weak_ptr<weave::Command>& command) {
200c18c7cfe350a5e671deaf1c2eaa30868e6ceb67fPaul Westbrook    auto cmd = command.lock();
201c18c7cfe350a5e671deaf1c2eaa30868e6ceb67fPaul Westbrook    if (!cmd)
202c18c7cfe350a5e671deaf1c2eaa30868e6ceb67fPaul Westbrook      return;
203c18c7cfe350a5e671deaf1c2eaa30868e6ceb67fPaul Westbrook    LOG(INFO) << "received command: " << cmd->GetName();
204c4305600835b91630f9ca4b10ad9070ea55a726cVitaly Buka    const auto& params = cmd->GetParameters();
205c18c7cfe350a5e671deaf1c2eaa30868e6ceb67fPaul Westbrook    int32_t brightness_value = 0;
206c4305600835b91630f9ca4b10ad9070ea55a726cVitaly Buka    if (params.GetInteger("brightness", &brightness_value)) {
207c18c7cfe350a5e671deaf1c2eaa30868e6ceb67fPaul Westbrook      // Display this command in terminal.
208c18c7cfe350a5e671deaf1c2eaa30868e6ceb67fPaul Westbrook      LOG(INFO) << cmd->GetName() << " brightness: " << brightness_value;
209c18c7cfe350a5e671deaf1c2eaa30868e6ceb67fPaul Westbrook
210c18c7cfe350a5e671deaf1c2eaa30868e6ceb67fPaul Westbrook      if (brightness_state_ != brightness_value) {
211c18c7cfe350a5e671deaf1c2eaa30868e6ceb67fPaul Westbrook        brightness_state_ = brightness_value;
212c18c7cfe350a5e671deaf1c2eaa30868e6ceb67fPaul Westbrook        UpdateLightState();
213c18c7cfe350a5e671deaf1c2eaa30868e6ceb67fPaul Westbrook      }
214c18c7cfe350a5e671deaf1c2eaa30868e6ceb67fPaul Westbrook      cmd->Complete({}, nullptr);
215c18c7cfe350a5e671deaf1c2eaa30868e6ceb67fPaul Westbrook      return;
216c18c7cfe350a5e671deaf1c2eaa30868e6ceb67fPaul Westbrook    }
2173fb474e64c9ed199919313321e46da3a531ecc7dJohan Euphrosine    weave::ErrorPtr error;
21848a8669ddc2e8d785aad9ad18a5abbf8f1224fdeVitaly Buka    weave::Error::AddTo(&error, FROM_HERE, "invalid_parameter_value",
2193fb474e64c9ed199919313321e46da3a531ecc7dJohan Euphrosine                        "Invalid parameters");
220c18c7cfe350a5e671deaf1c2eaa30868e6ceb67fPaul Westbrook    cmd->Abort(error.get(), nullptr);
221c18c7cfe350a5e671deaf1c2eaa30868e6ceb67fPaul Westbrook  }
222c18c7cfe350a5e671deaf1c2eaa30868e6ceb67fPaul Westbrook
2233fb474e64c9ed199919313321e46da3a531ecc7dJohan Euphrosine  void OnOnOffSetConfig(const std::weak_ptr<weave::Command>& command) {
224c18c7cfe350a5e671deaf1c2eaa30868e6ceb67fPaul Westbrook    auto cmd = command.lock();
225c18c7cfe350a5e671deaf1c2eaa30868e6ceb67fPaul Westbrook    if (!cmd)
226c18c7cfe350a5e671deaf1c2eaa30868e6ceb67fPaul Westbrook      return;
227c18c7cfe350a5e671deaf1c2eaa30868e6ceb67fPaul Westbrook    LOG(INFO) << "received command: " << cmd->GetName();
228c4305600835b91630f9ca4b10ad9070ea55a726cVitaly Buka    const auto& params = cmd->GetParameters();
229c18c7cfe350a5e671deaf1c2eaa30868e6ceb67fPaul Westbrook    std::string requested_state;
230c4305600835b91630f9ca4b10ad9070ea55a726cVitaly Buka    if (params.GetString("state", &requested_state)) {
231c18c7cfe350a5e671deaf1c2eaa30868e6ceb67fPaul Westbrook      LOG(INFO) << cmd->GetName() << " state: " << requested_state;
232c18c7cfe350a5e671deaf1c2eaa30868e6ceb67fPaul Westbrook
233c18c7cfe350a5e671deaf1c2eaa30868e6ceb67fPaul Westbrook      bool new_light_status = requested_state == "on";
234c18c7cfe350a5e671deaf1c2eaa30868e6ceb67fPaul Westbrook      if (new_light_status != light_status_) {
235c18c7cfe350a5e671deaf1c2eaa30868e6ceb67fPaul Westbrook        light_status_ = new_light_status;
236c18c7cfe350a5e671deaf1c2eaa30868e6ceb67fPaul Westbrook
237c18c7cfe350a5e671deaf1c2eaa30868e6ceb67fPaul Westbrook        LOG(INFO) << "Light is now: " << (light_status_ ? "ON" : "OFF");
238c18c7cfe350a5e671deaf1c2eaa30868e6ceb67fPaul Westbrook        UpdateLightState();
239c18c7cfe350a5e671deaf1c2eaa30868e6ceb67fPaul Westbrook      }
240c18c7cfe350a5e671deaf1c2eaa30868e6ceb67fPaul Westbrook      cmd->Complete({}, nullptr);
241c18c7cfe350a5e671deaf1c2eaa30868e6ceb67fPaul Westbrook      return;
242c18c7cfe350a5e671deaf1c2eaa30868e6ceb67fPaul Westbrook    }
2433fb474e64c9ed199919313321e46da3a531ecc7dJohan Euphrosine    weave::ErrorPtr error;
24448a8669ddc2e8d785aad9ad18a5abbf8f1224fdeVitaly Buka    weave::Error::AddTo(&error, FROM_HERE, "invalid_parameter_value",
2453fb474e64c9ed199919313321e46da3a531ecc7dJohan Euphrosine                        "Invalid parameters");
246c18c7cfe350a5e671deaf1c2eaa30868e6ceb67fPaul Westbrook    cmd->Abort(error.get(), nullptr);
247c18c7cfe350a5e671deaf1c2eaa30868e6ceb67fPaul Westbrook  }
248c18c7cfe350a5e671deaf1c2eaa30868e6ceb67fPaul Westbrook
24903cd192eceb46f936ad89e6ae04dac130202e18cPaul Westbrook  void OnColorXYSetConfig(const std::weak_ptr<weave::Command>& command) {
25003cd192eceb46f936ad89e6ae04dac130202e18cPaul Westbrook    auto cmd = command.lock();
25103cd192eceb46f936ad89e6ae04dac130202e18cPaul Westbrook    if (!cmd)
25203cd192eceb46f936ad89e6ae04dac130202e18cPaul Westbrook      return;
25303cd192eceb46f936ad89e6ae04dac130202e18cPaul Westbrook    LOG(INFO) << "received command: " << cmd->GetName();
254c4305600835b91630f9ca4b10ad9070ea55a726cVitaly Buka    const auto& params = cmd->GetParameters();
255c4305600835b91630f9ca4b10ad9070ea55a726cVitaly Buka    const base::DictionaryValue* colorXY = nullptr;
25605a979e3ad64a2e6c1986cf5151d032f672b6b2dPaul Westbrook    if (params.GetDictionary("colorSetting", &colorXY)) {
25703cd192eceb46f936ad89e6ae04dac130202e18cPaul Westbrook      bool updateState = false;
25803cd192eceb46f936ad89e6ae04dac130202e18cPaul Westbrook      double X = 0.0;
25903cd192eceb46f936ad89e6ae04dac130202e18cPaul Westbrook      double Y = 0.0;
26005a979e3ad64a2e6c1986cf5151d032f672b6b2dPaul Westbrook      if (colorXY->GetDouble("colorX", &X)) {
26103cd192eceb46f936ad89e6ae04dac130202e18cPaul Westbrook        color_X_ = X;
26203cd192eceb46f936ad89e6ae04dac130202e18cPaul Westbrook        updateState = true;
26303cd192eceb46f936ad89e6ae04dac130202e18cPaul Westbrook      }
26403cd192eceb46f936ad89e6ae04dac130202e18cPaul Westbrook
26505a979e3ad64a2e6c1986cf5151d032f672b6b2dPaul Westbrook      if (colorXY->GetDouble("colorY", &Y)) {
26603cd192eceb46f936ad89e6ae04dac130202e18cPaul Westbrook        color_Y_ = Y;
26703cd192eceb46f936ad89e6ae04dac130202e18cPaul Westbrook        updateState = true;
26803cd192eceb46f936ad89e6ae04dac130202e18cPaul Westbrook      }
26903cd192eceb46f936ad89e6ae04dac130202e18cPaul Westbrook
27003cd192eceb46f936ad89e6ae04dac130202e18cPaul Westbrook      if (updateState)
27103cd192eceb46f936ad89e6ae04dac130202e18cPaul Westbrook        UpdateLightState();
27203cd192eceb46f936ad89e6ae04dac130202e18cPaul Westbrook
27303cd192eceb46f936ad89e6ae04dac130202e18cPaul Westbrook      cmd->Complete({}, nullptr);
27403cd192eceb46f936ad89e6ae04dac130202e18cPaul Westbrook      return;
27503cd192eceb46f936ad89e6ae04dac130202e18cPaul Westbrook    }
27603cd192eceb46f936ad89e6ae04dac130202e18cPaul Westbrook
27703cd192eceb46f936ad89e6ae04dac130202e18cPaul Westbrook    weave::ErrorPtr error;
27848a8669ddc2e8d785aad9ad18a5abbf8f1224fdeVitaly Buka    weave::Error::AddTo(&error, FROM_HERE, "invalid_parameter_value",
27903cd192eceb46f936ad89e6ae04dac130202e18cPaul Westbrook                        "Invalid parameters");
28003cd192eceb46f936ad89e6ae04dac130202e18cPaul Westbrook    cmd->Abort(error.get(), nullptr);
28103cd192eceb46f936ad89e6ae04dac130202e18cPaul Westbrook  }
28203cd192eceb46f936ad89e6ae04dac130202e18cPaul Westbrook
2833fb474e64c9ed199919313321e46da3a531ecc7dJohan Euphrosine  void UpdateLightState() {
284c18c7cfe350a5e671deaf1c2eaa30868e6ceb67fPaul Westbrook    base::DictionaryValue state;
285c18c7cfe350a5e671deaf1c2eaa30868e6ceb67fPaul Westbrook    state.SetString("onOff.state", light_status_ ? "on" : "standby");
286c18c7cfe350a5e671deaf1c2eaa30868e6ceb67fPaul Westbrook    state.SetInteger("brightness.brightness", brightness_state_);
28703cd192eceb46f936ad89e6ae04dac130202e18cPaul Westbrook
28803cd192eceb46f936ad89e6ae04dac130202e18cPaul Westbrook    std::unique_ptr<base::DictionaryValue> colorXY(new base::DictionaryValue());
28903cd192eceb46f936ad89e6ae04dac130202e18cPaul Westbrook    colorXY->SetDouble("colorX", color_X_);
29003cd192eceb46f936ad89e6ae04dac130202e18cPaul Westbrook    colorXY->SetDouble("colorY", color_Y_);
291d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko    state.Set("colorXY.colorSetting", colorXY.release());
292d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko    device_->SetStateProperties(kComponent, state, nullptr);
293c18c7cfe350a5e671deaf1c2eaa30868e6ceb67fPaul Westbrook  }
294c18c7cfe350a5e671deaf1c2eaa30868e6ceb67fPaul Westbrook
2953fb474e64c9ed199919313321e46da3a531ecc7dJohan Euphrosine  weave::Device* device_{nullptr};
296c18c7cfe350a5e671deaf1c2eaa30868e6ceb67fPaul Westbrook
297c18c7cfe350a5e671deaf1c2eaa30868e6ceb67fPaul Westbrook  // Simulate the state of the light.
298d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko  bool light_status_{false};
299d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko  int32_t brightness_state_{0};
30003cd192eceb46f936ad89e6ae04dac130202e18cPaul Westbrook  double color_X_{0.0};
30103cd192eceb46f936ad89e6ae04dac130202e18cPaul Westbrook  double color_Y_{0.0};
302c18c7cfe350a5e671deaf1c2eaa30868e6ceb67fPaul Westbrook  base::WeakPtrFactory<LightHandler> weak_ptr_factory_{this};
303c18c7cfe350a5e671deaf1c2eaa30868e6ceb67fPaul Westbrook};
304c18c7cfe350a5e671deaf1c2eaa30868e6ceb67fPaul Westbrook
3053fb474e64c9ed199919313321e46da3a531ecc7dJohan Euphrosineint main(int argc, char** argv) {
3063fb474e64c9ed199919313321e46da3a531ecc7dJohan Euphrosine  Daemon::Options opts;
30704e628f7854b7252ccda1b303a8e99d840cf9a98Paul Westbrook  opts.model_id_ = "AIAAA";
3083fb474e64c9ed199919313321e46da3a531ecc7dJohan Euphrosine  if (!opts.Parse(argc, argv)) {
3093fb474e64c9ed199919313321e46da3a531ecc7dJohan Euphrosine    Daemon::Options::ShowUsage(argv[0]);
3103fb474e64c9ed199919313321e46da3a531ecc7dJohan Euphrosine    return 1;
3113fb474e64c9ed199919313321e46da3a531ecc7dJohan Euphrosine  }
3123fb474e64c9ed199919313321e46da3a531ecc7dJohan Euphrosine  Daemon daemon{opts};
3133fb474e64c9ed199919313321e46da3a531ecc7dJohan Euphrosine  LightHandler handler;
3143fb474e64c9ed199919313321e46da3a531ecc7dJohan Euphrosine  handler.Register(daemon.GetDevice());
3153fb474e64c9ed199919313321e46da3a531ecc7dJohan Euphrosine  daemon.Run();
3163fb474e64c9ed199919313321e46da3a531ecc7dJohan Euphrosine  return 0;
3173fb474e64c9ed199919313321e46da3a531ecc7dJohan Euphrosine}
318