Add support for virtual lock & light devices
Change-Id: Ib26fad33aee2618f0f299c1c4a970d7822a8d1df
Reviewed-on: https://weave-review.googlesource.com/1412
Reviewed-by: Paul Westbrook <pwestbro@google.com>
diff --git a/libweave/examples/daemon/light_handler.h b/libweave/examples/daemon/light_handler.h
new file mode 100644
index 0000000..08eb682
--- /dev/null
+++ b/libweave/examples/daemon/light_handler.h
@@ -0,0 +1,131 @@
+// 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 <weave/device.h>
+
+#include <base/bind.h>
+#include <base/memory/weak_ptr.h>
+
+namespace weave {
+namespace examples {
+namespace daemon {
+
+// LightHandler is a command handler example that shows
+// how to handle commands for a Weave light.
+class LightHandler {
+ public:
+ LightHandler() = default;
+ void Register(Device* device) {
+ device_ = device;
+
+ device->AddStateDefinitionsFromJson(R"({
+ "onOff": {"state": ["on", "standby"]},
+ "brightness": {"brightness": "integer"}
+ })");
+
+ device->SetStatePropertiesFromJson(R"({
+ "onOff":{"state": "standby"},
+ "brightness":{"brightness": 0}
+ })",
+ nullptr);
+
+ // Once bug b/25304415 is fixed, these should be changed
+ // to use the standard commands.
+ device->AddCommandDefinitionsFromJson(R"({
+ "onOff": {
+ "_setConfig":{
+ "parameters": {
+ "_state": ["on", "standby"]
+ }
+ }
+ },
+ "brightness": {
+ "_setConfig":{
+ "parameters": {
+ "_brightness": {
+ "type": "integer",
+ "minimum": 0,
+ "maximum": 100
+ }
+ }
+ }
+ }
+ })");
+ device->AddCommandHandler(
+ "onOff._setConfig",
+ base::Bind(&LightHandler::OnOnOffSetConfig,
+ weak_ptr_factory_.GetWeakPtr()));
+ device->AddCommandHandler(
+ "brightness._setConfig",
+ base::Bind(&LightHandler::OnBrightnessSetConfig,
+ weak_ptr_factory_.GetWeakPtr()));
+ }
+
+ private:
+ void OnBrightnessSetConfig(const std::weak_ptr<Command>& command) {
+ auto cmd = command.lock();
+ if (!cmd)
+ return;
+ LOG(INFO) << "received command: " << cmd->GetName();
+ int32_t brightness_value = 0;
+ if (cmd->GetParameters()->GetInteger("_brightness", &brightness_value)) {
+ // Display this command in terminal.
+ LOG(INFO) << cmd->GetName() << " brightness: " << brightness_value;
+
+ if (brightness_state_ != brightness_value) {
+ brightness_state_ = brightness_value;
+ UpdateLightState();
+ }
+ cmd->Complete({}, nullptr);
+ return;
+ }
+ ErrorPtr error;
+ Error::AddTo(&error, FROM_HERE, "example", "invalid_parameter_value",
+ "Invalid parameters");
+ cmd->Abort(error.get(), nullptr);
+ }
+
+ void OnOnOffSetConfig(const std::weak_ptr<Command>& command) {
+ auto cmd = command.lock();
+ if (!cmd)
+ return;
+ LOG(INFO) << "received command: " << cmd->GetName();
+ std::string requested_state;
+ if (cmd->GetParameters()->GetString("_state", &requested_state)) {
+ LOG(INFO) << cmd->GetName() << " state: " << requested_state;
+
+ bool new_light_status = requested_state == "on";
+ if (new_light_status != light_status_) {
+ light_status_ = new_light_status;
+
+ LOG(INFO) << "Light is now: " << (light_status_ ? "ON" : "OFF");
+ UpdateLightState();
+ }
+ cmd->Complete({}, nullptr);
+ return;
+ }
+ ErrorPtr error;
+ Error::AddTo(&error, FROM_HERE, "example", "invalid_parameter_value",
+ "Invalid parameters");
+ cmd->Abort(error.get(), nullptr);
+ }
+
+ void UpdateLightState(void) {
+ base::DictionaryValue state;
+ state.SetString("onOff.state", light_status_ ? "on" : "standby");
+ state.SetInteger("brightness.brightness", brightness_state_);
+ device_->SetStateProperties(state, nullptr);
+ }
+
+ Device* device_{nullptr};
+
+ // Simulate the state of the light.
+ bool light_status_;
+ int32_t brightness_state_;
+ base::WeakPtrFactory<LightHandler> weak_ptr_factory_{this};
+};
+
+} // namespace daemon
+} // namespace examples
+} // namespace weave
diff --git a/libweave/examples/daemon/lock_handler.h b/libweave/examples/daemon/lock_handler.h
new file mode 100644
index 0000000..71ff83a
--- /dev/null
+++ b/libweave/examples/daemon/lock_handler.h
@@ -0,0 +1,115 @@
+// 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 <weave/device.h>
+#include <weave/enum_to_string.h>
+
+#include <base/bind.h>
+#include <base/memory/weak_ptr.h>
+
+namespace weave {
+
+namespace lockstate {
+enum class LockState { kUnlocked, kLocked, kPartiallyLocked };
+
+const weave::EnumToStringMap<LockState>::Map kLockMapMethod[] = {
+ {LockState::kLocked, "locked"},
+ {LockState::kUnlocked, "unlocked"},
+ {LockState::kPartiallyLocked, "partiallyLocked"}};
+} // namespace lockstate
+
+template <>
+EnumToStringMap<lockstate::LockState>::EnumToStringMap()
+ : EnumToStringMap(lockstate::kLockMapMethod) {}
+
+namespace examples {
+namespace daemon {
+
+// LockHandler is a command handler example that shows
+// how to handle commands for a Weave lock.
+class LockHandler {
+ public:
+ LockHandler() = default;
+ void Register(Device* device) {
+ device_ = device;
+
+ device->AddStateDefinitionsFromJson(R"({
+ "_lock": {"lockedState": ["locked", "unlocked", "partiallyLocked"]}
+ })");
+
+ device->SetStatePropertiesFromJson(R"({
+ "_lock":{"lockedState": "locked"}
+ })",
+ nullptr);
+
+ // Once bug b/25304415 is fixed, and when the lock trait is published
+ // these should be changed to use the standard commands
+ device->AddCommandDefinitionsFromJson(R"({
+ "_lock": {
+ "_setConfig":{
+ "parameters": {
+ "_lockedState": ["locked", "unlocked"]
+ }
+ }
+ }
+ })");
+ device->AddCommandHandler(
+ "_lock._setConfig",
+ base::Bind(&LockHandler::OnLockSetConfig,
+ weak_ptr_factory_.GetWeakPtr()));
+ }
+
+ private:
+ void OnLockSetConfig(const std::weak_ptr<Command>& command) {
+ auto cmd = command.lock();
+ if (!cmd)
+ return;
+ LOG(INFO) << "received command: " << cmd->GetName();
+ std::string requested_state;
+ if (cmd->GetParameters()->GetString("_lockedState", &requested_state)) {
+ LOG(INFO) << cmd->GetName() << " state: " << requested_state;
+
+ lockstate::LockState new_lock_status;
+
+ if (!weave::StringToEnum(requested_state, &new_lock_status)) {
+ // Invalid lock state was specified.
+ ErrorPtr error;
+ Error::AddTo(&error, FROM_HERE, "example", "invalid_parameter_value",
+ "Invalid parameters");
+ cmd->Abort(error.get(), nullptr);
+ return;
+ }
+
+ if (new_lock_status != lock_state_) {
+ lock_state_ = new_lock_status;
+
+ LOG(INFO) << "Lock is now: " << requested_state;
+ UpdateLockState();
+ }
+ cmd->Complete({}, nullptr);
+ return;
+ }
+ ErrorPtr error;
+ Error::AddTo(&error, FROM_HERE, "example", "invalid_parameter_value",
+ "Invalid parameters");
+ cmd->Abort(error.get(), nullptr);
+ }
+
+ void UpdateLockState(void) {
+ base::DictionaryValue state;
+ std::string updated_state = weave::EnumToString(lock_state_);
+ state.SetString("lock.lockedState", updated_state);
+ device_->SetStateProperties(state, nullptr);
+ }
+
+ Device* device_{nullptr};
+
+ // Simulate the state of the light.
+ lockstate::LockState lock_state_{lockstate::LockState::kLocked};
+ base::WeakPtrFactory<LockHandler> weak_ptr_factory_{this};
+};
+
+} // namespace daemon
+} // namespace examples
+} // namespace weave
diff --git a/libweave/examples/daemon/main.cc b/libweave/examples/daemon/main.cc
index 263e730..3a4efe7 100644
--- a/libweave/examples/daemon/main.cc
+++ b/libweave/examples/daemon/main.cc
@@ -8,6 +8,8 @@
#include <base/bind.h>
#include "examples/daemon/ledflasher_handler.h"
+#include "examples/daemon/light_handler.h"
+#include "examples/daemon/lock_handler.h"
#include "examples/daemon/sample_handler.h"
#include "examples/provider/avahi_client.h"
@@ -33,7 +35,9 @@
<< "\t-d,--disable_security Disable privet security\n"
<< "\t--registration_ticket=TICKET Register device with the "
"given ticket\n"
- << "\t--disable_privet Disable local privet\n";
+ << "\t--disable_privet Disable local privet\n"
+ << "\t--type=UIDEVICEKIND Create a device with the "
+ "specified ui device kind\n";
}
void OnRegisterDeviceDone(weave::Device* device, weave::ErrorPtr error) {
@@ -50,6 +54,7 @@
bool disable_security = false;
bool disable_privet = false;
std::string registration_ticket;
+ std::string ui_device_kind;
for (int i = 1; i < argc; ++i) {
std::string arg = argv[i];
if (arg == "-h" || arg == "--help") {
@@ -75,6 +80,13 @@
return 1;
}
logging::SetMinLogLevel(-std::stoi(arg.substr(pos + 1)));
+ } else if (arg.find("--type") != std::string::npos) {
+ auto pos = arg.find("=");
+ if (pos == std::string::npos) {
+ ShowUsage(argv[0]);
+ return 1;
+ }
+ ui_device_kind = arg.substr(pos + 1);
} else {
ShowUsage(argv[0]);
return 1;
@@ -111,6 +123,20 @@
sample.Register(device.get());
ledFlasher.Register(device.get());
+ // If the caller specified a particular ui device kind, register the
+ // correspoinding device handlers
+ // TODO: move this to before device registration, as this should also
+ // cause a particular model manifest to be used.
+ weave::examples::daemon::LightHandler lightHandler;
+ weave::examples::daemon::LockHandler lockHandler;
+ if (!ui_device_kind.empty()) {
+ if (ui_device_kind == "light") {
+ lightHandler.Register(device.get());
+ } else if (ui_device_kind == "lock") {
+ lockHandler.Register(device.get());
+ }
+ }
+
task_runner.Run();
LOG(INFO) << "exit";