1 // Copyright 2015 The Weave Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "examples/daemon/common/daemon.h"
6
7 #include <weave/device.h>
8
9 #include <base/bind.h>
10 #include <base/memory/weak_ptr.h>
11
12 namespace {
13
14 const char kTraits[] = R"({
15 "onOff": {
16 "commands": {
17 "setConfig": {
18 "minimalRole": "user",
19 "parameters": {
20 "state": {
21 "type": "string",
22 "enum": [ "on", "standby" ]
23 }
24 }
25 }
26 },
27 "state": {
28 "state": {
29 "type": "string",
30 "enum": [ "on", "standby" ],
31 "isRequired": true
32 }
33 }
34 },
35 "brightness": {
36 "commands": {
37 "setConfig": {
38 "minimalRole": "user",
39 "parameters": {
40 "brightness": {
41 "type": "integer",
42 "minimum": 0,
43 "maximum": 100
44 }
45 }
46 }
47 },
48 "state": {
49 "brightness": {
50 "type": "integer",
51 "isRequired": true,
52 "minimum": 0,
53 "maximum": 100
54 }
55 }
56 },
57 "colorXY": {
58 "commands": {
59 "setConfig": {
60 "minimalRole": "user",
61 "parameters": {
62 "colorSetting": {
63 "type": "object",
64 "required": [
65 "colorX",
66 "colorY"
67 ],
68 "properties": {
69 "colorX": {
70 "type": "number",
71 "minimum": 0.0,
72 "maximum": 1.0
73 },
74 "colorY": {
75 "type": "number",
76 "minimum": 0.0,
77 "maximum": 1.0
78 }
79 },
80 "additionalProperties": false
81 }
82 },
83 "errors": ["colorOutOfRange"]
84 }
85 },
86 "state": {
87 "colorSetting": {
88 "type": "object",
89 "isRequired": true,
90 "required": [ "colorX", "colorY" ],
91 "properties": {
92 "colorX": {
93 "type": "number",
94 "minimum": 0.0,
95 "maximum": 1.0
96 },
97 "colorY": {
98 "type": "number",
99 "minimum": 0.0,
100 "maximum": 1.0
101 }
102 }
103 },
104 "colorCapRed": {
105 "type": "object",
106 "isRequired": true,
107 "required": [ "colorX", "colorY" ],
108 "properties": {
109 "colorX": {
110 "type": "number",
111 "minimum": 0.0,
112 "maximum": 1.0
113 },
114 "colorY": {
115 "type": "number",
116 "minimum": 0.0,
117 "maximum": 1.0
118 }
119 }
120 },
121 "colorCapGreen": {
122 "type": "object",
123 "isRequired": true,
124 "required": [ "colorX", "colorY" ],
125 "properties": {
126 "colorX": {
127 "type": "number",
128 "minimum": 0.0,
129 "maximum": 1.0
130 },
131 "colorY": {
132 "type": "number",
133 "minimum": 0.0,
134 "maximum": 1.0
135 }
136 }
137 },
138 "colorCapBlue": {
139 "type": "object",
140 "isRequired": true,
141 "required": [ "colorX", "colorY" ],
142 "properties": {
143 "colorX": {
144 "type": "number",
145 "minimum": 0.0,
146 "maximum": 1.0
147 },
148 "colorY": {
149 "type": "number",
150 "minimum": 0.0,
151 "maximum": 1.0
152 }
153 }
154 }
155 }
156 }
157 })";
158
159 const char kDefaultState[] = R"({
160 "colorXY": {
161 "colorSetting": {"colorX": 0, "colorY": 0},
162 "colorCapRed": {"colorX": 0.674, "colorY": 0.322},
163 "colorCapGreen":{"colorX": 0.408, "colorY": 0.517},
164 "colorCapBlue": {"colorX": 0.168, "colorY": 0.041}
165 }
166 })";
167
168 const char kComponent[] = "light";
169
170 } // anonymous namespace
171
172 // LightHandler is a command handler example that shows
173 // how to handle commands for a Weave light.
174 class LightHandler {
175 public:
176 LightHandler() = default;
Register(weave::Device * device)177 void Register(weave::Device* device) {
178 device_ = device;
179
180 device->AddTraitDefinitionsFromJson(kTraits);
181 CHECK(device->AddComponent(kComponent, {"onOff", "brightness", "colorXY"},
182 nullptr));
183 CHECK(
184 device->SetStatePropertiesFromJson(kComponent, kDefaultState, nullptr));
185 UpdateLightState();
186
187 device->AddCommandHandler(kComponent, "onOff.setConfig",
188 base::Bind(&LightHandler::OnOnOffSetConfig,
189 weak_ptr_factory_.GetWeakPtr()));
190 device->AddCommandHandler(kComponent, "brightness.setConfig",
191 base::Bind(&LightHandler::OnBrightnessSetConfig,
192 weak_ptr_factory_.GetWeakPtr()));
193 device->AddCommandHandler(kComponent, "colorXY.setConfig",
194 base::Bind(&LightHandler::OnColorXYSetConfig,
195 weak_ptr_factory_.GetWeakPtr()));
196 }
197
198 private:
OnBrightnessSetConfig(const std::weak_ptr<weave::Command> & command)199 void OnBrightnessSetConfig(const std::weak_ptr<weave::Command>& command) {
200 auto cmd = command.lock();
201 if (!cmd)
202 return;
203 LOG(INFO) << "received command: " << cmd->GetName();
204 const auto& params = cmd->GetParameters();
205 int32_t brightness_value = 0;
206 if (params.GetInteger("brightness", &brightness_value)) {
207 // Display this command in terminal.
208 LOG(INFO) << cmd->GetName() << " brightness: " << brightness_value;
209
210 if (brightness_state_ != brightness_value) {
211 brightness_state_ = brightness_value;
212 UpdateLightState();
213 }
214 cmd->Complete({}, nullptr);
215 return;
216 }
217 weave::ErrorPtr error;
218 weave::Error::AddTo(&error, FROM_HERE, "invalid_parameter_value",
219 "Invalid parameters");
220 cmd->Abort(error.get(), nullptr);
221 }
222
OnOnOffSetConfig(const std::weak_ptr<weave::Command> & command)223 void OnOnOffSetConfig(const std::weak_ptr<weave::Command>& command) {
224 auto cmd = command.lock();
225 if (!cmd)
226 return;
227 LOG(INFO) << "received command: " << cmd->GetName();
228 const auto& params = cmd->GetParameters();
229 std::string requested_state;
230 if (params.GetString("state", &requested_state)) {
231 LOG(INFO) << cmd->GetName() << " state: " << requested_state;
232
233 bool new_light_status = requested_state == "on";
234 if (new_light_status != light_status_) {
235 light_status_ = new_light_status;
236
237 LOG(INFO) << "Light is now: " << (light_status_ ? "ON" : "OFF");
238 UpdateLightState();
239 }
240 cmd->Complete({}, nullptr);
241 return;
242 }
243 weave::ErrorPtr error;
244 weave::Error::AddTo(&error, FROM_HERE, "invalid_parameter_value",
245 "Invalid parameters");
246 cmd->Abort(error.get(), nullptr);
247 }
248
OnColorXYSetConfig(const std::weak_ptr<weave::Command> & command)249 void OnColorXYSetConfig(const std::weak_ptr<weave::Command>& command) {
250 auto cmd = command.lock();
251 if (!cmd)
252 return;
253 LOG(INFO) << "received command: " << cmd->GetName();
254 const auto& params = cmd->GetParameters();
255 const base::DictionaryValue* colorXY = nullptr;
256 if (params.GetDictionary("colorSetting", &colorXY)) {
257 bool updateState = false;
258 double X = 0.0;
259 double Y = 0.0;
260 if (colorXY->GetDouble("colorX", &X)) {
261 color_X_ = X;
262 updateState = true;
263 }
264
265 if (colorXY->GetDouble("colorY", &Y)) {
266 color_Y_ = Y;
267 updateState = true;
268 }
269
270 if (updateState)
271 UpdateLightState();
272
273 cmd->Complete({}, nullptr);
274 return;
275 }
276
277 weave::ErrorPtr error;
278 weave::Error::AddTo(&error, FROM_HERE, "invalid_parameter_value",
279 "Invalid parameters");
280 cmd->Abort(error.get(), nullptr);
281 }
282
UpdateLightState()283 void UpdateLightState() {
284 base::DictionaryValue state;
285 state.SetString("onOff.state", light_status_ ? "on" : "standby");
286 state.SetInteger("brightness.brightness", brightness_state_);
287
288 std::unique_ptr<base::DictionaryValue> colorXY(new base::DictionaryValue());
289 colorXY->SetDouble("colorX", color_X_);
290 colorXY->SetDouble("colorY", color_Y_);
291 state.Set("colorXY.colorSetting", colorXY.release());
292 device_->SetStateProperties(kComponent, state, nullptr);
293 }
294
295 weave::Device* device_{nullptr};
296
297 // Simulate the state of the light.
298 bool light_status_{false};
299 int32_t brightness_state_{0};
300 double color_X_{0.0};
301 double color_Y_{0.0};
302 base::WeakPtrFactory<LightHandler> weak_ptr_factory_{this};
303 };
304
main(int argc,char ** argv)305 int main(int argc, char** argv) {
306 Daemon::Options opts;
307 opts.model_id_ = "AIAAA";
308 if (!opts.Parse(argc, argv)) {
309 Daemon::Options::ShowUsage(argv[0]);
310 return 1;
311 }
312 Daemon daemon{opts};
313 LightHandler handler;
314 handler.Register(daemon.GetDevice());
315 daemon.Run();
316 return 0;
317 }
318