Oven virtual device sample initial commit. Used as weave device for CES
demo.
Virtual oven implements temperatureSetting, temperatureSensor, and
brightness traits.
Change-Id: I33ec5c841ad102377166086668cbb0e1b78755dc
Reviewed-on: https://weave-review.googlesource.com/1867
Reviewed-by: Peng Ying <pying@google.com>
diff --git a/examples/daemon/examples.gyp b/examples/daemon/examples.gyp
index 2b497a5..d63c5e4 100644
--- a/examples/daemon/examples.gyp
+++ b/examples/daemon/examples.gyp
@@ -8,7 +8,8 @@
'light/daemon.gyp:weave_daemon_light',
'lock/daemon.gyp:weave_daemon_lock',
'ledflasher/daemon.gyp:weave_daemon_ledflasher',
- 'speaker/daemon.gyp:weave_daemon_speaker'
+ 'speaker/daemon.gyp:weave_daemon_speaker',
+ 'oven/daemon.gyp:weave_daemon_oven',
]
}
]
diff --git a/examples/daemon/oven/daemon.gyp b/examples/daemon/oven/daemon.gyp
new file mode 100644
index 0000000..44b4798
--- /dev/null
+++ b/examples/daemon/oven/daemon.gyp
@@ -0,0 +1,18 @@
+# Copyright 2015 The Weave Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+{
+ 'targets': [
+ {
+ 'target_name': 'weave_daemon_oven',
+ 'type': 'executable',
+ 'sources': [
+ 'oven.cc',
+ ],
+ 'dependencies': [
+ '<@(DEPTH)/libweave_standalone.gyp:libweave',
+ '<@(DEPTH)/examples/provider/provider.gyp:libweave_provider',
+ ]
+ }
+ ]
+}
diff --git a/examples/daemon/oven/oven.cc b/examples/daemon/oven/oven.cc
new file mode 100644
index 0000000..79fc925
--- /dev/null
+++ b/examples/daemon/oven/oven.cc
@@ -0,0 +1,263 @@
+// Copyright 2015 The Weave Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "examples/daemon/common/daemon.h"
+
+#include <weave/device.h>
+#include <weave/provider/task_runner.h>
+
+#include <base/bind.h>
+#include <base/memory/weak_ptr.h>
+
+namespace {
+// Time for sensor temperature to match setting temperature
+const double kWarmUpTime = 60.0;
+// Oven max temp
+const double kMaxTemp = 300.0;
+// Oven min temp
+const double kMinTemp = 20.0;
+
+const char kTraits[] = R"({
+ "temperatureSetting": {
+ "commands": {
+ "setConfig": {
+ "minimalRole": "user",
+ "parameters": {
+ "units": {
+ "type": "string"
+ },
+ "tempSetting": {
+ "type": "number"
+ }
+ }
+ }
+ },
+ "state": {
+ "supportedUnits": {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "enum": [
+ "celsius",
+ "fahrenheit",
+ "kelvin"
+ ]
+ }
+ },
+ "units": {
+ "type": "string"
+ },
+ "tempSetting": {
+ "type": "number"
+ },
+ "maxTempSetting": {
+ "type": "number"
+ },
+ "minTempSetting": {
+ "type": "number"
+ }
+ }
+ },
+ "temperatureSensor": {
+ "state": {
+ "supportedUnits": {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "enum": [
+ "celsius",
+ "fahrenheit",
+ "kelvin"
+ ]
+ }
+ },
+ "units": {
+ "type": "string"
+ },
+ "value": {
+ "type": "number"
+ }
+ }
+ },
+ "brightness": {
+ "commands": {
+ "setConfig": {
+ "minimalRole": "user",
+ "parameters": {
+ "brightness": {
+ "type": "integer",
+ "minimum": 0,
+ "maximum": 100
+ }
+ }
+ }
+ },
+ "state": {
+ "brightness": {
+ "type": "number"
+ }
+ }
+ }
+})";
+
+const char kComponent[] = "oven";
+} // anonymous namespace
+
+// OvenHandler is a virtual oven example
+// It implements the following commands from traits:
+// - temperatureSetting: sets the temperature for the oven
+// - brightness: sets the brightness of the oven light
+// It exposes the following states from traits:
+// - temperatureSetting: temperature setting for the oven
+// - temperatureSensor: current oven temperature
+// - brightness: current oven brightness
+class OvenHandler {
+ public:
+ OvenHandler(weave::provider::TaskRunner* task_runner)
+ : task_runner_{task_runner} {}
+
+ void Register(weave::Device* device) {
+ device_ = device;
+
+ device->AddTraitDefinitionsFromJson(kTraits);
+ CHECK(device->AddComponent(
+ kComponent, {"temperatureSetting", "temperatureSensor", "brightness"},
+ nullptr));
+
+ UpdateOvenState();
+
+ device->AddCommandHandler(kComponent, "temperatureSetting.setConfig",
+ base::Bind(&OvenHandler::OnSetTempCommand,
+ weak_ptr_factory_.GetWeakPtr()));
+
+ device->AddCommandHandler(kComponent, "brightness.setConfig",
+ base::Bind(&OvenHandler::OnSetBrightnessCommand,
+ weak_ptr_factory_.GetWeakPtr()));
+ }
+
+private:
+ void OnSetTempCommand(const std::weak_ptr<weave::Command>& command) {
+ auto cmd = command.lock();
+ if (!cmd)
+ return;
+ LOG(INFO) << "received command: " << cmd->GetName();
+
+ const auto& params = cmd->GetParameters();
+ std::string units;
+ double temp;
+
+ if (params.GetString("units", &units) &&
+ params.GetDouble("tempSetting", &temp)) {
+ units_ = units;
+ target_temperature_ = temp;
+
+ UpdateOvenState();
+
+ cmd->Complete({}, nullptr);
+ LOG(INFO) << cmd->GetName() << " updated oven, matching temp";
+
+ if (target_temperature_ != current_temperature_ && !is_match_ticking_) {
+ double tickIncrement = ((target_temperature_ - current_temperature_) /
+ kWarmUpTime);
+ DoTick(tickIncrement);
+ }
+ return;
+ }
+
+ weave::ErrorPtr error;
+ weave::Error::AddTo(&error, FROM_HERE, "example", "invalid_parameter_value",
+ "Invalid parameters");
+ cmd->Abort(error.get(), nullptr);
+ }
+
+ void OnSetBrightnessCommand(const std::weak_ptr<weave::Command>& command) {
+ auto cmd = command.lock();
+ if (!cmd)
+ return;
+ LOG(INFO) << "received command: " << cmd->GetName();
+
+ const auto& params = cmd->GetParameters();
+
+ int brightness;
+ if (params.GetInteger("brightness", &brightness)) {
+ brightness_ = brightness;
+
+ UpdateOvenState();
+
+ cmd->Complete({}, nullptr);
+ return;
+ }
+
+ weave::ErrorPtr error;
+ weave::Error::AddTo(&error, FROM_HERE, "example", "invalid_parameter_value",
+ "Invalid parameters");
+ cmd->Abort(error.get(), nullptr);
+ }
+
+ void UpdateOvenState() {
+ base::DictionaryValue state;
+ base::ListValue supportedUnits;
+ supportedUnits.AppendStrings({"celsius"});
+
+ state.SetString("temperatureSensor.units", units_);
+ state.SetDouble("temperatureSensor.value", current_temperature_);
+ state.Set("temperatureSensor.supportedUnits", supportedUnits.DeepCopy());
+
+ state.SetString("temperatureSetting.units", units_);
+ state.SetDouble("temperatureSetting.tempSetting", target_temperature_);
+ state.Set("temperatureSetting.supportedUnits", supportedUnits.DeepCopy());
+ state.SetDouble("temperatureSetting.maxTempSetting", kMaxTemp);
+ state.SetDouble("temperatureSetting.minTempSetting", kMinTemp);
+
+ state.SetInteger("brightness.brightness", brightness_);
+
+ device_->SetStateProperties(kComponent, state, nullptr);
+ }
+
+ void DoTick(double tickIncrement) {
+ LOG(INFO) << "Oven matching temp tick";
+
+ if (std::fabs(target_temperature_ - current_temperature_) >=
+ tickIncrement) {
+ is_match_ticking_ = true;
+ current_temperature_ += tickIncrement;
+ UpdateOvenState();
+ task_runner_->PostDelayedTask(
+ FROM_HERE, base::Bind(&OvenHandler::DoTick,
+ weak_ptr_factory_.GetWeakPtr(), tickIncrement),
+ base::TimeDelta::FromSeconds(1));
+ return;
+ }
+
+ is_match_ticking_ = false;
+ current_temperature_ = target_temperature_;
+ UpdateOvenState();
+
+ LOG(INFO) << "Oven temp matched";
+ }
+
+ weave::Device* device_{nullptr};
+ weave::provider::TaskRunner* task_runner_{nullptr};
+
+ std::string units_ = "celsius";
+ double target_temperature_ = 0.0;
+ double current_temperature_ = 0.0;
+ int brightness_ = 0;
+ bool is_match_ticking_ = false;
+
+ base::WeakPtrFactory<OvenHandler> weak_ptr_factory_{this};
+};
+
+int main(int argc, char** argv) {
+ Daemon::Options opts;
+ if (!opts.Parse(argc, argv)) {
+ Daemon::Options::ShowUsage(argv[0]);
+ return 1;
+ }
+ Daemon daemon{opts};
+ OvenHandler handler{daemon.GetTaskRunner()};
+ handler.Register(daemon.GetDevice());
+ daemon.Run();
+ return 0;
+}