blob: 298fcafe00d930c0cec7848d756c754399a17385 [file] [log] [blame]
Paul Westbrookc18c7cf2015-10-27 06:38:59 -07001// 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
Johan Euphrosine3fb474e2015-10-29 15:23:53 -07005#include "examples/daemon/common/daemon.h"
6
Paul Westbrookc18c7cf2015-10-27 06:38:59 -07007#include <weave/device.h>
8
9#include <base/bind.h>
10#include <base/memory/weak_ptr.h>
11
Alex Vakulenkod6db0492015-12-07 16:55:19 -080012namespace {
13
14const 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",
Alex Vakulenko8d0cfef2015-12-15 18:40:05 -080030 "enum": [ "on", "standby" ],
31 "isRequired": true
Alex Vakulenkod6db0492015-12-07 16:55:19 -080032 }
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 },
Alex Vakulenko8d0cfef2015-12-15 18:40:05 -080048 "state": {
49 "brightness": {
50 "type": "integer",
51 "isRequired": true,
52 "minimum": 0,
53 "maximum": 100
54 }
55 }
Alex Vakulenkod6db0492015-12-07 16:55:19 -080056 },
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 }
Alex Vakulenko8d0cfef2015-12-15 18:40:05 -080082 },
83 "errors": ["colorOutOfRange"]
Alex Vakulenkod6db0492015-12-07 16:55:19 -080084 }
85 },
86 "state": {
87 "colorSetting": {
Alex Vakulenko8d0cfef2015-12-15 18:40:05 -080088 "type": "object",
89 "isRequired": true,
90 "required": [ "colorX", "colorY" ],
Alex Vakulenkod6db0492015-12-07 16:55:19 -080091 "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": {
Alex Vakulenko8d0cfef2015-12-15 18:40:05 -0800105 "type": "object",
106 "isRequired": true,
107 "required": [ "colorX", "colorY" ],
Alex Vakulenkod6db0492015-12-07 16:55:19 -0800108 "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": {
Alex Vakulenko8d0cfef2015-12-15 18:40:05 -0800122 "type": "object",
123 "isRequired": true,
124 "required": [ "colorX", "colorY" ],
Alex Vakulenkod6db0492015-12-07 16:55:19 -0800125 "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": {
Alex Vakulenko8d0cfef2015-12-15 18:40:05 -0800139 "type": "object",
140 "isRequired": true,
141 "required": [ "colorX", "colorY" ],
Alex Vakulenkod6db0492015-12-07 16:55:19 -0800142 "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
159const 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
168const char kComponent[] = "light";
169
170} // anonymous namespace
171
Paul Westbrookc18c7cf2015-10-27 06:38:59 -0700172// LightHandler is a command handler example that shows
173// how to handle commands for a Weave light.
174class LightHandler {
175 public:
176 LightHandler() = default;
Johan Euphrosine3fb474e2015-10-29 15:23:53 -0700177 void Register(weave::Device* device) {
Paul Westbrookc18c7cf2015-10-27 06:38:59 -0700178 device_ = device;
179
Alex Vakulenkod6db0492015-12-07 16:55:19 -0800180 device->AddTraitDefinitionsFromJson(kTraits);
181 CHECK(device->AddComponent(kComponent, {"onOff", "brightness", "colorXY"},
182 nullptr));
Vitaly Buka34668e72015-12-15 14:46:47 -0800183 CHECK(
184 device->SetStatePropertiesFromJson(kComponent, kDefaultState, nullptr));
Alex Vakulenkod6db0492015-12-07 16:55:19 -0800185 UpdateLightState();
Paul Westbrookc18c7cf2015-10-27 06:38:59 -0700186
Alex Vakulenkod6db0492015-12-07 16:55:19 -0800187 device->AddCommandHandler(kComponent, "onOff.setConfig",
Johan Euphrosine3fb474e2015-10-29 15:23:53 -0700188 base::Bind(&LightHandler::OnOnOffSetConfig,
189 weak_ptr_factory_.GetWeakPtr()));
Alex Vakulenkod6db0492015-12-07 16:55:19 -0800190 device->AddCommandHandler(kComponent, "brightness.setConfig",
Johan Euphrosine3fb474e2015-10-29 15:23:53 -0700191 base::Bind(&LightHandler::OnBrightnessSetConfig,
192 weak_ptr_factory_.GetWeakPtr()));
Alex Vakulenkod6db0492015-12-07 16:55:19 -0800193 device->AddCommandHandler(kComponent, "colorXY.setConfig",
Paul Westbrook03cd1922015-11-16 18:03:57 -0800194 base::Bind(&LightHandler::OnColorXYSetConfig,
195 weak_ptr_factory_.GetWeakPtr()));
Paul Westbrookc18c7cf2015-10-27 06:38:59 -0700196 }
197
198 private:
Johan Euphrosine3fb474e2015-10-29 15:23:53 -0700199 void OnBrightnessSetConfig(const std::weak_ptr<weave::Command>& command) {
Paul Westbrookc18c7cf2015-10-27 06:38:59 -0700200 auto cmd = command.lock();
201 if (!cmd)
202 return;
203 LOG(INFO) << "received command: " << cmd->GetName();
Vitaly Bukac4305602015-11-24 23:33:09 -0800204 const auto& params = cmd->GetParameters();
Paul Westbrookc18c7cf2015-10-27 06:38:59 -0700205 int32_t brightness_value = 0;
Vitaly Bukac4305602015-11-24 23:33:09 -0800206 if (params.GetInteger("brightness", &brightness_value)) {
Paul Westbrookc18c7cf2015-10-27 06:38:59 -0700207 // 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 }
Johan Euphrosine3fb474e2015-10-29 15:23:53 -0700217 weave::ErrorPtr error;
218 weave::Error::AddTo(&error, FROM_HERE, "example", "invalid_parameter_value",
219 "Invalid parameters");
Paul Westbrookc18c7cf2015-10-27 06:38:59 -0700220 cmd->Abort(error.get(), nullptr);
221 }
222
Johan Euphrosine3fb474e2015-10-29 15:23:53 -0700223 void OnOnOffSetConfig(const std::weak_ptr<weave::Command>& command) {
Paul Westbrookc18c7cf2015-10-27 06:38:59 -0700224 auto cmd = command.lock();
225 if (!cmd)
226 return;
227 LOG(INFO) << "received command: " << cmd->GetName();
Vitaly Bukac4305602015-11-24 23:33:09 -0800228 const auto& params = cmd->GetParameters();
Paul Westbrookc18c7cf2015-10-27 06:38:59 -0700229 std::string requested_state;
Vitaly Bukac4305602015-11-24 23:33:09 -0800230 if (params.GetString("state", &requested_state)) {
Paul Westbrookc18c7cf2015-10-27 06:38:59 -0700231 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 }
Johan Euphrosine3fb474e2015-10-29 15:23:53 -0700243 weave::ErrorPtr error;
244 weave::Error::AddTo(&error, FROM_HERE, "example", "invalid_parameter_value",
245 "Invalid parameters");
Paul Westbrookc18c7cf2015-10-27 06:38:59 -0700246 cmd->Abort(error.get(), nullptr);
247 }
248
Paul Westbrook03cd1922015-11-16 18:03:57 -0800249 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();
Vitaly Bukac4305602015-11-24 23:33:09 -0800254 const auto& params = cmd->GetParameters();
255 const base::DictionaryValue* colorXY = nullptr;
Paul Westbrook05a979e2015-12-04 03:27:22 -0800256 if (params.GetDictionary("colorSetting", &colorXY)) {
Paul Westbrook03cd1922015-11-16 18:03:57 -0800257 bool updateState = false;
258 double X = 0.0;
259 double Y = 0.0;
Paul Westbrook05a979e2015-12-04 03:27:22 -0800260 if (colorXY->GetDouble("colorX", &X)) {
Paul Westbrook03cd1922015-11-16 18:03:57 -0800261 color_X_ = X;
262 updateState = true;
263 }
264
Paul Westbrook05a979e2015-12-04 03:27:22 -0800265 if (colorXY->GetDouble("colorY", &Y)) {
Paul Westbrook03cd1922015-11-16 18:03:57 -0800266 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, "example", "invalid_parameter_value",
279 "Invalid parameters");
280 cmd->Abort(error.get(), nullptr);
281 }
282
Johan Euphrosine3fb474e2015-10-29 15:23:53 -0700283 void UpdateLightState() {
Paul Westbrookc18c7cf2015-10-27 06:38:59 -0700284 base::DictionaryValue state;
285 state.SetString("onOff.state", light_status_ ? "on" : "standby");
286 state.SetInteger("brightness.brightness", brightness_state_);
Paul Westbrook03cd1922015-11-16 18:03:57 -0800287
288 std::unique_ptr<base::DictionaryValue> colorXY(new base::DictionaryValue());
289 colorXY->SetDouble("colorX", color_X_);
290 colorXY->SetDouble("colorY", color_Y_);
Alex Vakulenkod6db0492015-12-07 16:55:19 -0800291 state.Set("colorXY.colorSetting", colorXY.release());
292 device_->SetStateProperties(kComponent, state, nullptr);
Paul Westbrookc18c7cf2015-10-27 06:38:59 -0700293 }
294
Johan Euphrosine3fb474e2015-10-29 15:23:53 -0700295 weave::Device* device_{nullptr};
Paul Westbrookc18c7cf2015-10-27 06:38:59 -0700296
297 // Simulate the state of the light.
Alex Vakulenkod6db0492015-12-07 16:55:19 -0800298 bool light_status_{false};
299 int32_t brightness_state_{0};
Paul Westbrook03cd1922015-11-16 18:03:57 -0800300 double color_X_{0.0};
301 double color_Y_{0.0};
Paul Westbrookc18c7cf2015-10-27 06:38:59 -0700302 base::WeakPtrFactory<LightHandler> weak_ptr_factory_{this};
303};
304
Johan Euphrosine3fb474e2015-10-29 15:23:53 -0700305int main(int argc, char** argv) {
306 Daemon::Options opts;
Paul Westbrook04e628f2015-12-08 18:33:21 -0800307 opts.model_id_ = "AIAAA";
Johan Euphrosine3fb474e2015-10-29 15:23:53 -0700308 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}