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