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; 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: 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 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 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 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 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