oven.cc revision aef87f5214d4e8b5924281d82dae2c8156f4203a
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#include <weave/provider/task_runner.h> 9 10#include <base/bind.h> 11#include <base/memory/weak_ptr.h> 12 13namespace { 14// Time for sensor temperature to match setting temperature 15const double kWarmUpTime = 60.0; 16// Oven max temp 17const double kMaxTemp = 300.0; 18// Oven min temp 19const double kMinTemp = 20.0; 20 21const char kTraits[] = R"({ 22 "temperatureSetting": { 23 "commands": { 24 "setConfig": { 25 "minimalRole": "user", 26 "parameters": { 27 "units": { 28 "type": "string" 29 }, 30 "tempSetting": { 31 "type": "number" 32 } 33 } 34 } 35 }, 36 "state": { 37 "supportedUnits": { 38 "type": "array", 39 "items": { 40 "type": "string", 41 "enum": [ 42 "celsius", 43 "fahrenheit", 44 "kelvin" 45 ] 46 } 47 }, 48 "units": { 49 "type": "string" 50 }, 51 "tempSetting": { 52 "type": "number" 53 }, 54 "maxTempSetting": { 55 "type": "number" 56 }, 57 "minTempSetting": { 58 "type": "number" 59 } 60 } 61 }, 62 "temperatureSensor": { 63 "state": { 64 "supportedUnits": { 65 "type": "array", 66 "items": { 67 "type": "string", 68 "enum": [ 69 "celsius", 70 "fahrenheit", 71 "kelvin" 72 ] 73 } 74 }, 75 "units": { 76 "type": "string" 77 }, 78 "value": { 79 "type": "number" 80 } 81 } 82 }, 83 "brightness": { 84 "commands": { 85 "setConfig": { 86 "minimalRole": "user", 87 "parameters": { 88 "brightness": { 89 "type": "integer", 90 "minimum": 0, 91 "maximum": 100 92 } 93 } 94 } 95 }, 96 "state": { 97 "brightness": { 98 "type": "number" 99 } 100 } 101 } 102})"; 103 104const char kComponent[] = "oven"; 105} // anonymous namespace 106 107// OvenHandler is a virtual oven example 108// It implements the following commands from traits: 109// - temperatureSetting: sets the temperature for the oven 110// - brightness: sets the brightness of the oven light 111// It exposes the following states from traits: 112// - temperatureSetting: temperature setting for the oven 113// - temperatureSensor: current oven temperature 114// - brightness: current oven brightness 115class OvenHandler { 116 public: 117 OvenHandler(weave::provider::TaskRunner* task_runner) 118 : task_runner_{task_runner} {} 119 120 void Register(weave::Device* device) { 121 device_ = device; 122 123 device->AddTraitDefinitionsFromJson(kTraits); 124 CHECK(device->AddComponent( 125 kComponent, {"temperatureSetting", "temperatureSensor", "brightness"}, 126 nullptr)); 127 128 UpdateOvenState(); 129 130 device->AddCommandHandler(kComponent, "temperatureSetting.setConfig", 131 base::Bind(&OvenHandler::OnSetTempCommand, 132 weak_ptr_factory_.GetWeakPtr())); 133 134 device->AddCommandHandler(kComponent, "brightness.setConfig", 135 base::Bind(&OvenHandler::OnSetBrightnessCommand, 136 weak_ptr_factory_.GetWeakPtr())); 137 } 138 139private: 140 void OnSetTempCommand(const std::weak_ptr<weave::Command>& command) { 141 auto cmd = command.lock(); 142 if (!cmd) 143 return; 144 LOG(INFO) << "received command: " << cmd->GetName(); 145 146 const auto& params = cmd->GetParameters(); 147 std::string units; 148 double temp; 149 150 if (params.GetString("units", &units) && 151 params.GetDouble("tempSetting", &temp)) { 152 units_ = units; 153 target_temperature_ = temp; 154 155 UpdateOvenState(); 156 157 cmd->Complete({}, nullptr); 158 LOG(INFO) << cmd->GetName() << " updated oven, matching temp"; 159 160 if (target_temperature_ != current_temperature_ && !is_match_ticking_) { 161 double tickIncrement = ((target_temperature_ - current_temperature_) / 162 kWarmUpTime); 163 DoTick(tickIncrement); 164 } 165 return; 166 } 167 168 weave::ErrorPtr error; 169 weave::Error::AddTo(&error, FROM_HERE, "example", "invalid_parameter_value", 170 "Invalid parameters"); 171 cmd->Abort(error.get(), nullptr); 172 } 173 174 void OnSetBrightnessCommand(const std::weak_ptr<weave::Command>& command) { 175 auto cmd = command.lock(); 176 if (!cmd) 177 return; 178 LOG(INFO) << "received command: " << cmd->GetName(); 179 180 const auto& params = cmd->GetParameters(); 181 182 int brightness; 183 if (params.GetInteger("brightness", &brightness)) { 184 brightness_ = brightness; 185 186 UpdateOvenState(); 187 188 cmd->Complete({}, nullptr); 189 return; 190 } 191 192 weave::ErrorPtr error; 193 weave::Error::AddTo(&error, FROM_HERE, "example", "invalid_parameter_value", 194 "Invalid parameters"); 195 cmd->Abort(error.get(), nullptr); 196 } 197 198 void UpdateOvenState() { 199 base::DictionaryValue state; 200 base::ListValue supportedUnits; 201 supportedUnits.AppendStrings({"celsius"}); 202 203 state.SetString("temperatureSensor.units", units_); 204 state.SetDouble("temperatureSensor.value", current_temperature_); 205 state.Set("temperatureSensor.supportedUnits", supportedUnits.DeepCopy()); 206 207 state.SetString("temperatureSetting.units", units_); 208 state.SetDouble("temperatureSetting.tempSetting", target_temperature_); 209 state.Set("temperatureSetting.supportedUnits", supportedUnits.DeepCopy()); 210 state.SetDouble("temperatureSetting.maxTempSetting", kMaxTemp); 211 state.SetDouble("temperatureSetting.minTempSetting", kMinTemp); 212 213 state.SetInteger("brightness.brightness", brightness_); 214 215 device_->SetStateProperties(kComponent, state, nullptr); 216 } 217 218 void DoTick(double tickIncrement) { 219 LOG(INFO) << "Oven matching temp tick"; 220 221 if (std::fabs(target_temperature_ - current_temperature_) >= 222 tickIncrement) { 223 is_match_ticking_ = true; 224 current_temperature_ += tickIncrement; 225 UpdateOvenState(); 226 task_runner_->PostDelayedTask( 227 FROM_HERE, base::Bind(&OvenHandler::DoTick, 228 weak_ptr_factory_.GetWeakPtr(), tickIncrement), 229 base::TimeDelta::FromSeconds(1)); 230 return; 231 } 232 233 is_match_ticking_ = false; 234 current_temperature_ = target_temperature_; 235 UpdateOvenState(); 236 237 LOG(INFO) << "Oven temp matched"; 238 } 239 240 weave::Device* device_{nullptr}; 241 weave::provider::TaskRunner* task_runner_{nullptr}; 242 243 std::string units_ = "celsius"; 244 double target_temperature_ = 0.0; 245 double current_temperature_ = 0.0; 246 int brightness_ = 0; 247 bool is_match_ticking_ = false; 248 249 base::WeakPtrFactory<OvenHandler> weak_ptr_factory_{this}; 250}; 251 252int main(int argc, char** argv) { 253 Daemon::Options opts; 254 if (!opts.Parse(argc, argv)) { 255 Daemon::Options::ShowUsage(argv[0]); 256 return 1; 257 } 258 Daemon daemon{opts}; 259 OvenHandler handler{daemon.GetTaskRunner()}; 260 handler.Register(daemon.GetDevice()); 261 daemon.Run(); 262 return 0; 263} 264