examples/daemon: re-organize sample handler
split commands to show one weave feature at a time:
- hello: command handling with args and results
- ping: device state
- countdown: long running command w/ progress
Bug: 24992153
Change-Id: Ib901239170287225c239c224c4fc9aa0b4112856
Reviewed-on: https://weave-review.googlesource.com/1347
Reviewed-by: Johan Euphrosine <proppy@google.com>
diff --git a/libweave/examples/daemon/greeter_handler.h b/libweave/examples/daemon/greeter_handler.h
deleted file mode 100644
index 7f71a06..0000000
--- a/libweave/examples/daemon/greeter_handler.h
+++ /dev/null
@@ -1,111 +0,0 @@
-// 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/provider/task_runner.h>
-
-#include <base/bind.h>
-#include <base/memory/weak_ptr.h>
-
-namespace weave {
-namespace examples {
-namespace daemon {
-
-class GreeterHandler {
- public:
- GreeterHandler(provider::TaskRunner* task_runner)
- : task_runner_{task_runner} {}
- void Register(Device* device) {
- device_ = device;
-
- device->AddStateDefinitionsFromJson(R"({
- "_greeter": {"_greetings_counter":"integer"}
- })");
-
- device->SetStatePropertiesFromJson(R"({
- "_greeter": {"_greetings_counter": 0}
- })",
- nullptr);
-
- device->AddCommandDefinitionsFromJson(R"({
- "_greeter": {
- "_greet": {
- "minimalRole": "user",
- "parameters": {
- "_name": "string",
- "_count": {"minimum": 1, "maximum": 100}
- },
- "progress": { "_todo": "integer"},
- "results": { "_greeting": "string" }
- }
- }
- })");
- device->AddCommandHandler("_greeter._greet",
- base::Bind(&GreeterHandler::OnGreetCommand,
- weak_ptr_factory_.GetWeakPtr()));
- }
-
- private:
- void DoGreet(const std::weak_ptr<Command>& command, int todo) {
- auto cmd = command.lock();
- if (!cmd)
- return;
-
- std::string name;
- if (!cmd->GetParameters()->GetString("_name", &name)) {
- ErrorPtr error;
- Error::AddTo(&error, FROM_HERE, "example",
- "invalid_parameter_value", "Name is missing");
- cmd->Abort(error.get(), nullptr);
- return;
- }
-
- if (todo-- > 0) {
- LOG(INFO) << "Hello " << name;
-
- base::DictionaryValue progress;
- progress.SetInteger("_todo", todo);
- cmd->SetProgress(progress, nullptr);
-
- base::DictionaryValue state;
- state.SetInteger("_greeter._greetings_counter", ++counter_);
- device_->SetStateProperties(state, nullptr);
- }
-
- if (todo > 0) {
- task_runner_->PostDelayedTask(
- FROM_HERE, base::Bind(&GreeterHandler::DoGreet,
- weak_ptr_factory_.GetWeakPtr(), command, todo),
- base::TimeDelta::FromSeconds(1));
- return;
- }
-
- base::DictionaryValue result;
- result.SetString("_greeting", "Hello " + name);
- cmd->Complete(result, nullptr);
- LOG(INFO) << cmd->GetName() << " command finished: " << result;
- LOG(INFO) << "New state: " << *device_->GetState();
- }
-
- void OnGreetCommand(const std::weak_ptr<Command>& command) {
- auto cmd = command.lock();
- if (!cmd)
- return;
- LOG(INFO) << "received command: " << cmd->GetName();
-
- int todo = 1;
- cmd->GetParameters()->GetInteger("_count", &todo);
- DoGreet(command, todo);
- }
-
- Device* device_{nullptr};
- provider::TaskRunner* task_runner_{nullptr};
-
- int counter_{0};
- base::WeakPtrFactory<GreeterHandler> weak_ptr_factory_{this};
-};
-
-} // namespace daemon
-} // namespace examples
-} // namespace weave
diff --git a/libweave/examples/daemon/ledflasher_handler.h b/libweave/examples/daemon/ledflasher_handler.h
index fba5197..812a3d4 100644
--- a/libweave/examples/daemon/ledflasher_handler.h
+++ b/libweave/examples/daemon/ledflasher_handler.h
@@ -18,6 +18,8 @@
const size_t kLedCount = 3;
} // namespace
+// LedFlasherHandler is a complete command handler example that shows
+// how to handle commands that modify device state.
class LedFlasherHandler {
public:
LedFlasherHandler() {}
@@ -84,7 +86,7 @@
}
ErrorPtr error;
Error::AddTo(&error, FROM_HERE, "example", "invalid_parameter_value",
- "Invalid parameters");
+ "Invalid parameters");
cmd->Abort(error.get(), nullptr);
}
@@ -105,7 +107,7 @@
}
ErrorPtr error;
Error::AddTo(&error, FROM_HERE, "example", "invalid_parameter_value",
- "Invalid parameters");
+ "Invalid parameters");
cmd->Abort(error.get(), nullptr);
}
diff --git a/libweave/examples/daemon/main.cc b/libweave/examples/daemon/main.cc
index 2c3841a..d49576a 100644
--- a/libweave/examples/daemon/main.cc
+++ b/libweave/examples/daemon/main.cc
@@ -7,6 +7,9 @@
#include <base/bind.h>
+#include "examples/daemon/ledflasher_handler.h"
+#include "examples/daemon/sample_handler.h"
+
#include "examples/provider/avahi_client.h"
#include "examples/provider/bluez_client.h"
#include "examples/provider/curl_http_client.h"
@@ -16,9 +19,6 @@
#include "examples/provider/file_config_store.h"
#include "examples/provider/wifi_manager.h"
-#include "examples/daemon/greeter_handler.h"
-#include "examples/daemon/ledflasher_handler.h"
-
namespace {
// Supported LED count on this device
@@ -108,9 +108,9 @@
base::Bind(&OnRegisterDeviceDone, device.get()));
}
- weave::examples::daemon::GreeterHandler greeter{&task_runner};
+ weave::examples::daemon::SampleHandler sample{&task_runner};
weave::examples::daemon::LedFlasherHandler ledFlasher;
- greeter.Register(device.get());
+ sample.Register(device.get());
ledFlasher.Register(device.get());
task_runner.Run();
diff --git a/libweave/examples/daemon/sample_handler.h b/libweave/examples/daemon/sample_handler.h
new file mode 100644
index 0000000..eca3452
--- /dev/null
+++ b/libweave/examples/daemon/sample_handler.h
@@ -0,0 +1,160 @@
+// 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/provider/task_runner.h>
+
+#include <base/bind.h>
+#include <base/memory/weak_ptr.h>
+
+namespace weave {
+namespace examples {
+namespace daemon {
+
+// SampleHandler is a command handler example.
+// It implements the following commands:
+// - _hello: handle a command with an argument and set its results.
+// - _ping: update device state.
+// - _countdown: handle long running command and report progress.
+class SampleHandler {
+ public:
+ SampleHandler(provider::TaskRunner* task_runner)
+ : task_runner_{task_runner} {}
+ void Register(Device* device) {
+ device_ = device;
+
+ device->AddCommandDefinitionsFromJson(R"({
+ "_sample": {
+ "_hello": {
+ "minimalRole": "user",
+ "parameters": {
+ "_name": "string"
+ },
+ "results": { "_reply": "string" }
+ },
+ "_ping": {
+ "minimalRole": "user",
+ "results": {}
+ },
+ "_countdown": {
+ "minimalRole": "user",
+ "parameters": {
+ "_seconds": {"minimum": 1, "maximum": 25}
+ },
+ "progress": { "_seconds_left": "integer"},
+ "results": {}
+ }
+ }
+ })");
+
+ device->AddStateDefinitionsFromJson(R"({
+ "_sample": {"_ping_count":"integer"}
+ })");
+
+ device->SetStatePropertiesFromJson(R"({
+ "_sample": {"_ping_count": 0}
+ })",
+ nullptr);
+
+ device->AddCommandHandler("_sample._hello",
+ base::Bind(&SampleHandler::OnHelloCommand,
+ weak_ptr_factory_.GetWeakPtr()));
+ device->AddCommandHandler("_sample._ping",
+ base::Bind(&SampleHandler::OnPingCommand,
+ weak_ptr_factory_.GetWeakPtr()));
+ device->AddCommandHandler("_sample._countdown",
+ base::Bind(&SampleHandler::OnCountdownCommand,
+ weak_ptr_factory_.GetWeakPtr()));
+ }
+
+ private:
+ void OnHelloCommand(const std::weak_ptr<Command>& command) {
+ auto cmd = command.lock();
+ if (!cmd)
+ return;
+ LOG(INFO) << "received command: " << cmd->GetName();
+
+ std::string name;
+ if (!cmd->GetParameters()->GetString("_name", &name)) {
+ ErrorPtr error;
+ Error::AddTo(&error, FROM_HERE, "example", "invalid_parameter_value",
+ "Name is missing");
+ cmd->Abort(error.get(), nullptr);
+ return;
+ }
+
+ base::DictionaryValue result;
+ result.SetString("_reply", "Hello " + name);
+ cmd->Complete(result, nullptr);
+ LOG(INFO) << cmd->GetName() << " command finished: " << result;
+ }
+
+ void OnPingCommand(const std::weak_ptr<Command>& command) {
+ auto cmd = command.lock();
+ if (!cmd)
+ return;
+ LOG(INFO) << "received command: " << cmd->GetName();
+
+ base::DictionaryValue state;
+ state.SetInteger("_sample._ping_count", ++ping_count_);
+ device_->SetStateProperties(state, nullptr);
+ LOG(INFO) << "New state: " << *device_->GetState();
+
+ base::DictionaryValue result;
+ cmd->Complete(result, nullptr);
+
+ LOG(INFO) << cmd->GetName() << " command finished: " << result;
+ }
+
+ void OnCountdownCommand(const std::weak_ptr<Command>& command) {
+ auto cmd = command.lock();
+ if (!cmd)
+ return;
+ LOG(INFO) << "received command: " << cmd->GetName();
+
+ int seconds;
+ if (!cmd->GetParameters()->GetInteger("_seconds", &seconds))
+ seconds = 10;
+
+ LOG(INFO) << "starting countdown";
+ DoTick(cmd, seconds);
+ }
+
+ void DoTick(const std::weak_ptr<Command>& command, int seconds) {
+ auto cmd = command.lock();
+ if (!cmd)
+ return;
+
+ if (seconds > 0) {
+ std::string todo;
+ cmd->GetParameters()->GetString("_todo", &todo);
+ LOG(INFO) << "countdown tick: " << seconds << " seconds left";
+
+ base::DictionaryValue progress;
+ progress.SetInteger("_seconds_left", seconds);
+ cmd->SetProgress(progress, nullptr);
+ task_runner_->PostDelayedTask(
+ FROM_HERE,
+ base::Bind(&SampleHandler::DoTick, weak_ptr_factory_.GetWeakPtr(),
+ command, --seconds),
+ base::TimeDelta::FromSeconds(1));
+ return;
+ }
+
+ base::DictionaryValue result;
+ cmd->Complete(result, nullptr);
+ LOG(INFO) << "countdown finished";
+ LOG(INFO) << cmd->GetName() << " command finished: " << result;
+ }
+
+ Device* device_{nullptr};
+ provider::TaskRunner* task_runner_{nullptr};
+
+ int ping_count_{0};
+ base::WeakPtrFactory<SampleHandler> weak_ptr_factory_{this};
+};
+
+} // namespace daemon
+} // namespace examples
+} // namespace weave