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