blob: 905a977d62507a0af5cf38138d4880f165dbaaa1 [file] [log] [blame]
Johan Euphrosine9eaad2c2015-10-15 20:17:39 -07001// Copyright 2015 The Weave Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
Johan Euphrosine3fb474e2015-10-29 15:23:53 -07005#include "examples/daemon/common/daemon.h"
6
Johan Euphrosine9eaad2c2015-10-15 20:17:39 -07007#include <weave/device.h>
8#include <weave/provider/task_runner.h>
9
10#include <base/bind.h>
11#include <base/memory/weak_ptr.h>
12
Johan Euphrosine9eaad2c2015-10-15 20:17:39 -070013// SampleHandler is a command handler example.
14// It implements the following commands:
15// - _hello: handle a command with an argument and set its results.
16// - _ping: update device state.
17// - _countdown: handle long running command and report progress.
18class SampleHandler {
19 public:
Johan Euphrosine3fb474e2015-10-29 15:23:53 -070020 SampleHandler(weave::provider::TaskRunner* task_runner)
Johan Euphrosine9eaad2c2015-10-15 20:17:39 -070021 : task_runner_{task_runner} {}
Johan Euphrosine3fb474e2015-10-29 15:23:53 -070022 void Register(weave::Device* device) {
Johan Euphrosine9eaad2c2015-10-15 20:17:39 -070023 device_ = device;
24
25 device->AddCommandDefinitionsFromJson(R"({
26 "_sample": {
27 "_hello": {
28 "minimalRole": "user",
29 "parameters": {
30 "_name": "string"
31 },
32 "results": { "_reply": "string" }
33 },
34 "_ping": {
35 "minimalRole": "user",
36 "results": {}
37 },
38 "_countdown": {
39 "minimalRole": "user",
40 "parameters": {
41 "_seconds": {"minimum": 1, "maximum": 25}
42 },
43 "progress": { "_seconds_left": "integer"},
44 "results": {}
45 }
46 }
47 })");
48
49 device->AddStateDefinitionsFromJson(R"({
50 "_sample": {"_ping_count":"integer"}
51 })");
52
53 device->SetStatePropertiesFromJson(R"({
54 "_sample": {"_ping_count": 0}
55 })",
56 nullptr);
57
58 device->AddCommandHandler("_sample._hello",
59 base::Bind(&SampleHandler::OnHelloCommand,
60 weak_ptr_factory_.GetWeakPtr()));
61 device->AddCommandHandler("_sample._ping",
62 base::Bind(&SampleHandler::OnPingCommand,
63 weak_ptr_factory_.GetWeakPtr()));
64 device->AddCommandHandler("_sample._countdown",
65 base::Bind(&SampleHandler::OnCountdownCommand,
66 weak_ptr_factory_.GetWeakPtr()));
67 }
68
69 private:
Johan Euphrosine3fb474e2015-10-29 15:23:53 -070070 void OnHelloCommand(const std::weak_ptr<weave::Command>& command) {
Johan Euphrosine9eaad2c2015-10-15 20:17:39 -070071 auto cmd = command.lock();
72 if (!cmd)
73 return;
74 LOG(INFO) << "received command: " << cmd->GetName();
75
76 std::string name;
77 if (!cmd->GetParameters()->GetString("_name", &name)) {
Johan Euphrosine3fb474e2015-10-29 15:23:53 -070078 weave::ErrorPtr error;
79 weave::Error::AddTo(&error, FROM_HERE, "example",
80 "invalid_parameter_value", "Name is missing");
Johan Euphrosine9eaad2c2015-10-15 20:17:39 -070081 cmd->Abort(error.get(), nullptr);
82 return;
83 }
84
85 base::DictionaryValue result;
86 result.SetString("_reply", "Hello " + name);
87 cmd->Complete(result, nullptr);
88 LOG(INFO) << cmd->GetName() << " command finished: " << result;
89 }
90
Johan Euphrosine3fb474e2015-10-29 15:23:53 -070091 void OnPingCommand(const std::weak_ptr<weave::Command>& command) {
Johan Euphrosine9eaad2c2015-10-15 20:17:39 -070092 auto cmd = command.lock();
93 if (!cmd)
94 return;
95 LOG(INFO) << "received command: " << cmd->GetName();
96
97 base::DictionaryValue state;
98 state.SetInteger("_sample._ping_count", ++ping_count_);
99 device_->SetStateProperties(state, nullptr);
100 LOG(INFO) << "New state: " << *device_->GetState();
101
102 base::DictionaryValue result;
103 cmd->Complete(result, nullptr);
104
105 LOG(INFO) << cmd->GetName() << " command finished: " << result;
106 }
107
Johan Euphrosine3fb474e2015-10-29 15:23:53 -0700108 void OnCountdownCommand(const std::weak_ptr<weave::Command>& command) {
Johan Euphrosine9eaad2c2015-10-15 20:17:39 -0700109 auto cmd = command.lock();
110 if (!cmd)
111 return;
112 LOG(INFO) << "received command: " << cmd->GetName();
113
114 int seconds;
115 if (!cmd->GetParameters()->GetInteger("_seconds", &seconds))
116 seconds = 10;
117
118 LOG(INFO) << "starting countdown";
119 DoTick(cmd, seconds);
120 }
121
Johan Euphrosine3fb474e2015-10-29 15:23:53 -0700122 void DoTick(const std::weak_ptr<weave::Command>& command, int seconds) {
Johan Euphrosine9eaad2c2015-10-15 20:17:39 -0700123 auto cmd = command.lock();
124 if (!cmd)
125 return;
126
127 if (seconds > 0) {
128 std::string todo;
129 cmd->GetParameters()->GetString("_todo", &todo);
130 LOG(INFO) << "countdown tick: " << seconds << " seconds left";
131
132 base::DictionaryValue progress;
133 progress.SetInteger("_seconds_left", seconds);
134 cmd->SetProgress(progress, nullptr);
135 task_runner_->PostDelayedTask(
136 FROM_HERE,
137 base::Bind(&SampleHandler::DoTick, weak_ptr_factory_.GetWeakPtr(),
138 command, --seconds),
139 base::TimeDelta::FromSeconds(1));
140 return;
141 }
142
143 base::DictionaryValue result;
144 cmd->Complete(result, nullptr);
145 LOG(INFO) << "countdown finished";
146 LOG(INFO) << cmd->GetName() << " command finished: " << result;
147 }
148
Johan Euphrosine3fb474e2015-10-29 15:23:53 -0700149 weave::Device* device_{nullptr};
150 weave::provider::TaskRunner* task_runner_{nullptr};
Johan Euphrosine9eaad2c2015-10-15 20:17:39 -0700151
152 int ping_count_{0};
153 base::WeakPtrFactory<SampleHandler> weak_ptr_factory_{this};
154};
155
Johan Euphrosine3fb474e2015-10-29 15:23:53 -0700156int main(int argc, char** argv) {
157 Daemon::Options opts;
158 if (!opts.Parse(argc, argv)) {
159 Daemon::Options::ShowUsage(argv[0]);
160 return 1;
161 }
162 Daemon daemon{opts};
163 SampleHandler handler{daemon.GetTaskRunner()};
164 handler.Register(daemon.GetDevice());
165 daemon.Run();
166 return 0;
167}