19eaad2c113edde4f674d8d12d0308caa408670cfJohan Euphrosine// Copyright 2015 The Weave Authors. All rights reserved. 29eaad2c113edde4f674d8d12d0308caa408670cfJohan Euphrosine// Use of this source code is governed by a BSD-style license that can be 39eaad2c113edde4f674d8d12d0308caa408670cfJohan Euphrosine// found in the LICENSE file. 49eaad2c113edde4f674d8d12d0308caa408670cfJohan Euphrosine 53fb474e64c9ed199919313321e46da3a531ecc7dJohan Euphrosine#include "examples/daemon/common/daemon.h" 63fb474e64c9ed199919313321e46da3a531ecc7dJohan Euphrosine 79eaad2c113edde4f674d8d12d0308caa408670cfJohan Euphrosine#include <weave/device.h> 89eaad2c113edde4f674d8d12d0308caa408670cfJohan Euphrosine#include <weave/provider/task_runner.h> 99eaad2c113edde4f674d8d12d0308caa408670cfJohan Euphrosine 109eaad2c113edde4f674d8d12d0308caa408670cfJohan Euphrosine#include <base/bind.h> 119eaad2c113edde4f674d8d12d0308caa408670cfJohan Euphrosine#include <base/memory/weak_ptr.h> 129eaad2c113edde4f674d8d12d0308caa408670cfJohan Euphrosine 13d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenkonamespace { 14d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko 15d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenkoconst char kTraits[] = R"({ 16d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko "_sample": { 17d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko "commands": { 188d0cfefae24985025a934ea5461a51472c59cfc0Alex Vakulenko "hello": { 19d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko "minimalRole": "user", 20d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko "parameters": { 218d0cfefae24985025a934ea5461a51472c59cfc0Alex Vakulenko "name": { "type": "string" } 22e6fee32eeccd56bc0e07e513aa53e31042baff7bVitaly Buka }, 23e6fee32eeccd56bc0e07e513aa53e31042baff7bVitaly Buka "results": { 24e6fee32eeccd56bc0e07e513aa53e31042baff7bVitaly Buka "reply": { "type": "string" } 25d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko } 26d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko }, 278d0cfefae24985025a934ea5461a51472c59cfc0Alex Vakulenko "ping": { 288d0cfefae24985025a934ea5461a51472c59cfc0Alex Vakulenko "minimalRole": "user", 298d0cfefae24985025a934ea5461a51472c59cfc0Alex Vakulenko "parameters": {} 30d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko }, 318d0cfefae24985025a934ea5461a51472c59cfc0Alex Vakulenko "countdown": { 32d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko "minimalRole": "user", 33d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko "parameters": { 348d0cfefae24985025a934ea5461a51472c59cfc0Alex Vakulenko "seconds": { 35d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko "type": "integer", 36d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko "minimum": 1, 37d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko "maximum": 25 38d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko } 39d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko } 40d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko } 41d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko }, 42d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko "state": { 438d0cfefae24985025a934ea5461a51472c59cfc0Alex Vakulenko "pingCount": { "type": "integer" } 44d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko } 45d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko } 46d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko})"; 47d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko 48d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenkoconst char kComponent[] = "sample"; 49d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko 50d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko} // anonymous namespace 51d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko 529eaad2c113edde4f674d8d12d0308caa408670cfJohan Euphrosine// SampleHandler is a command handler example. 539eaad2c113edde4f674d8d12d0308caa408670cfJohan Euphrosine// It implements the following commands: 549eaad2c113edde4f674d8d12d0308caa408670cfJohan Euphrosine// - _hello: handle a command with an argument and set its results. 559eaad2c113edde4f674d8d12d0308caa408670cfJohan Euphrosine// - _ping: update device state. 569eaad2c113edde4f674d8d12d0308caa408670cfJohan Euphrosine// - _countdown: handle long running command and report progress. 579eaad2c113edde4f674d8d12d0308caa408670cfJohan Euphrosineclass SampleHandler { 589eaad2c113edde4f674d8d12d0308caa408670cfJohan Euphrosine public: 593fb474e64c9ed199919313321e46da3a531ecc7dJohan Euphrosine SampleHandler(weave::provider::TaskRunner* task_runner) 609eaad2c113edde4f674d8d12d0308caa408670cfJohan Euphrosine : task_runner_{task_runner} {} 613fb474e64c9ed199919313321e46da3a531ecc7dJohan Euphrosine void Register(weave::Device* device) { 629eaad2c113edde4f674d8d12d0308caa408670cfJohan Euphrosine device_ = device; 639eaad2c113edde4f674d8d12d0308caa408670cfJohan Euphrosine 64d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko device->AddTraitDefinitionsFromJson(kTraits); 65d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko CHECK(device->AddComponent(kComponent, {"_sample"}, nullptr)); 66d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko CHECK(device->SetStatePropertiesFromJson( 678d0cfefae24985025a934ea5461a51472c59cfc0Alex Vakulenko kComponent, R"({"_sample": {"pingCount": 0}})", nullptr)); 689eaad2c113edde4f674d8d12d0308caa408670cfJohan Euphrosine 698d0cfefae24985025a934ea5461a51472c59cfc0Alex Vakulenko device->AddCommandHandler(kComponent, "_sample.hello", 709eaad2c113edde4f674d8d12d0308caa408670cfJohan Euphrosine base::Bind(&SampleHandler::OnHelloCommand, 719eaad2c113edde4f674d8d12d0308caa408670cfJohan Euphrosine weak_ptr_factory_.GetWeakPtr())); 728d0cfefae24985025a934ea5461a51472c59cfc0Alex Vakulenko device->AddCommandHandler(kComponent, "_sample.ping", 739eaad2c113edde4f674d8d12d0308caa408670cfJohan Euphrosine base::Bind(&SampleHandler::OnPingCommand, 749eaad2c113edde4f674d8d12d0308caa408670cfJohan Euphrosine weak_ptr_factory_.GetWeakPtr())); 758d0cfefae24985025a934ea5461a51472c59cfc0Alex Vakulenko device->AddCommandHandler(kComponent, "_sample.countdown", 769eaad2c113edde4f674d8d12d0308caa408670cfJohan Euphrosine base::Bind(&SampleHandler::OnCountdownCommand, 779eaad2c113edde4f674d8d12d0308caa408670cfJohan Euphrosine weak_ptr_factory_.GetWeakPtr())); 789eaad2c113edde4f674d8d12d0308caa408670cfJohan Euphrosine } 799eaad2c113edde4f674d8d12d0308caa408670cfJohan Euphrosine 809eaad2c113edde4f674d8d12d0308caa408670cfJohan Euphrosine private: 813fb474e64c9ed199919313321e46da3a531ecc7dJohan Euphrosine void OnHelloCommand(const std::weak_ptr<weave::Command>& command) { 829eaad2c113edde4f674d8d12d0308caa408670cfJohan Euphrosine auto cmd = command.lock(); 839eaad2c113edde4f674d8d12d0308caa408670cfJohan Euphrosine if (!cmd) 849eaad2c113edde4f674d8d12d0308caa408670cfJohan Euphrosine return; 859eaad2c113edde4f674d8d12d0308caa408670cfJohan Euphrosine LOG(INFO) << "received command: " << cmd->GetName(); 869eaad2c113edde4f674d8d12d0308caa408670cfJohan Euphrosine 87c4305600835b91630f9ca4b10ad9070ea55a726cVitaly Buka const auto& params = cmd->GetParameters(); 889eaad2c113edde4f674d8d12d0308caa408670cfJohan Euphrosine std::string name; 898d0cfefae24985025a934ea5461a51472c59cfc0Alex Vakulenko if (!params.GetString("name", &name)) { 903fb474e64c9ed199919313321e46da3a531ecc7dJohan Euphrosine weave::ErrorPtr error; 9148a8669ddc2e8d785aad9ad18a5abbf8f1224fdeVitaly Buka weave::Error::AddTo(&error, FROM_HERE, "invalid_parameter_value", 9248a8669ddc2e8d785aad9ad18a5abbf8f1224fdeVitaly Buka "Name is missing"); 939eaad2c113edde4f674d8d12d0308caa408670cfJohan Euphrosine cmd->Abort(error.get(), nullptr); 949eaad2c113edde4f674d8d12d0308caa408670cfJohan Euphrosine return; 959eaad2c113edde4f674d8d12d0308caa408670cfJohan Euphrosine } 969eaad2c113edde4f674d8d12d0308caa408670cfJohan Euphrosine 979eaad2c113edde4f674d8d12d0308caa408670cfJohan Euphrosine base::DictionaryValue result; 988d0cfefae24985025a934ea5461a51472c59cfc0Alex Vakulenko result.SetString("reply", "Hello " + name); 999eaad2c113edde4f674d8d12d0308caa408670cfJohan Euphrosine cmd->Complete(result, nullptr); 1009eaad2c113edde4f674d8d12d0308caa408670cfJohan Euphrosine LOG(INFO) << cmd->GetName() << " command finished: " << result; 1019eaad2c113edde4f674d8d12d0308caa408670cfJohan Euphrosine } 1029eaad2c113edde4f674d8d12d0308caa408670cfJohan Euphrosine 1033fb474e64c9ed199919313321e46da3a531ecc7dJohan Euphrosine void OnPingCommand(const std::weak_ptr<weave::Command>& command) { 1049eaad2c113edde4f674d8d12d0308caa408670cfJohan Euphrosine auto cmd = command.lock(); 1059eaad2c113edde4f674d8d12d0308caa408670cfJohan Euphrosine if (!cmd) 1069eaad2c113edde4f674d8d12d0308caa408670cfJohan Euphrosine return; 1079eaad2c113edde4f674d8d12d0308caa408670cfJohan Euphrosine LOG(INFO) << "received command: " << cmd->GetName(); 1089eaad2c113edde4f674d8d12d0308caa408670cfJohan Euphrosine 1098d0cfefae24985025a934ea5461a51472c59cfc0Alex Vakulenko device_->SetStateProperty(kComponent, "_sample.pingCount", 110d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko base::FundamentalValue{++ping_count_}, nullptr); 111ec9d8481ae5deaaf7901f944b06682e77b978881Alex Vakulenko LOG(INFO) << "New component state: " << device_->GetComponents(); 1129eaad2c113edde4f674d8d12d0308caa408670cfJohan Euphrosine 113e6fee32eeccd56bc0e07e513aa53e31042baff7bVitaly Buka cmd->Complete({}, nullptr); 1149eaad2c113edde4f674d8d12d0308caa408670cfJohan Euphrosine 115e6fee32eeccd56bc0e07e513aa53e31042baff7bVitaly Buka LOG(INFO) << cmd->GetName() << " command finished"; 1169eaad2c113edde4f674d8d12d0308caa408670cfJohan Euphrosine } 1179eaad2c113edde4f674d8d12d0308caa408670cfJohan Euphrosine 1183fb474e64c9ed199919313321e46da3a531ecc7dJohan Euphrosine void OnCountdownCommand(const std::weak_ptr<weave::Command>& command) { 1199eaad2c113edde4f674d8d12d0308caa408670cfJohan Euphrosine auto cmd = command.lock(); 1209eaad2c113edde4f674d8d12d0308caa408670cfJohan Euphrosine if (!cmd) 1219eaad2c113edde4f674d8d12d0308caa408670cfJohan Euphrosine return; 1229eaad2c113edde4f674d8d12d0308caa408670cfJohan Euphrosine LOG(INFO) << "received command: " << cmd->GetName(); 1239eaad2c113edde4f674d8d12d0308caa408670cfJohan Euphrosine 124c4305600835b91630f9ca4b10ad9070ea55a726cVitaly Buka const auto& params = cmd->GetParameters(); 1259eaad2c113edde4f674d8d12d0308caa408670cfJohan Euphrosine int seconds; 1268d0cfefae24985025a934ea5461a51472c59cfc0Alex Vakulenko if (!params.GetInteger("seconds", &seconds)) 1279eaad2c113edde4f674d8d12d0308caa408670cfJohan Euphrosine seconds = 10; 1289eaad2c113edde4f674d8d12d0308caa408670cfJohan Euphrosine 1299eaad2c113edde4f674d8d12d0308caa408670cfJohan Euphrosine LOG(INFO) << "starting countdown"; 1309eaad2c113edde4f674d8d12d0308caa408670cfJohan Euphrosine DoTick(cmd, seconds); 1319eaad2c113edde4f674d8d12d0308caa408670cfJohan Euphrosine } 1329eaad2c113edde4f674d8d12d0308caa408670cfJohan Euphrosine 1333fb474e64c9ed199919313321e46da3a531ecc7dJohan Euphrosine void DoTick(const std::weak_ptr<weave::Command>& command, int seconds) { 1349eaad2c113edde4f674d8d12d0308caa408670cfJohan Euphrosine auto cmd = command.lock(); 1359eaad2c113edde4f674d8d12d0308caa408670cfJohan Euphrosine if (!cmd) 1369eaad2c113edde4f674d8d12d0308caa408670cfJohan Euphrosine return; 1379eaad2c113edde4f674d8d12d0308caa408670cfJohan Euphrosine 1389eaad2c113edde4f674d8d12d0308caa408670cfJohan Euphrosine if (seconds > 0) { 1399eaad2c113edde4f674d8d12d0308caa408670cfJohan Euphrosine LOG(INFO) << "countdown tick: " << seconds << " seconds left"; 1409eaad2c113edde4f674d8d12d0308caa408670cfJohan Euphrosine base::DictionaryValue progress; 1418d0cfefae24985025a934ea5461a51472c59cfc0Alex Vakulenko progress.SetInteger("seconds_left", seconds); 1429eaad2c113edde4f674d8d12d0308caa408670cfJohan Euphrosine cmd->SetProgress(progress, nullptr); 1439eaad2c113edde4f674d8d12d0308caa408670cfJohan Euphrosine task_runner_->PostDelayedTask( 1449eaad2c113edde4f674d8d12d0308caa408670cfJohan Euphrosine FROM_HERE, 1459eaad2c113edde4f674d8d12d0308caa408670cfJohan Euphrosine base::Bind(&SampleHandler::DoTick, weak_ptr_factory_.GetWeakPtr(), 1469eaad2c113edde4f674d8d12d0308caa408670cfJohan Euphrosine command, --seconds), 1479eaad2c113edde4f674d8d12d0308caa408670cfJohan Euphrosine base::TimeDelta::FromSeconds(1)); 1489eaad2c113edde4f674d8d12d0308caa408670cfJohan Euphrosine return; 1499eaad2c113edde4f674d8d12d0308caa408670cfJohan Euphrosine } 1509eaad2c113edde4f674d8d12d0308caa408670cfJohan Euphrosine 151e6fee32eeccd56bc0e07e513aa53e31042baff7bVitaly Buka cmd->Complete({}, nullptr); 1529eaad2c113edde4f674d8d12d0308caa408670cfJohan Euphrosine LOG(INFO) << "countdown finished"; 153e6fee32eeccd56bc0e07e513aa53e31042baff7bVitaly Buka LOG(INFO) << cmd->GetName() << " command finished"; 1549eaad2c113edde4f674d8d12d0308caa408670cfJohan Euphrosine } 1559eaad2c113edde4f674d8d12d0308caa408670cfJohan Euphrosine 1563fb474e64c9ed199919313321e46da3a531ecc7dJohan Euphrosine weave::Device* device_{nullptr}; 1573fb474e64c9ed199919313321e46da3a531ecc7dJohan Euphrosine weave::provider::TaskRunner* task_runner_{nullptr}; 1589eaad2c113edde4f674d8d12d0308caa408670cfJohan Euphrosine 1599eaad2c113edde4f674d8d12d0308caa408670cfJohan Euphrosine int ping_count_{0}; 1609eaad2c113edde4f674d8d12d0308caa408670cfJohan Euphrosine base::WeakPtrFactory<SampleHandler> weak_ptr_factory_{this}; 1619eaad2c113edde4f674d8d12d0308caa408670cfJohan Euphrosine}; 1629eaad2c113edde4f674d8d12d0308caa408670cfJohan Euphrosine 1633fb474e64c9ed199919313321e46da3a531ecc7dJohan Euphrosineint main(int argc, char** argv) { 1643fb474e64c9ed199919313321e46da3a531ecc7dJohan Euphrosine Daemon::Options opts; 1653fb474e64c9ed199919313321e46da3a531ecc7dJohan Euphrosine if (!opts.Parse(argc, argv)) { 1663fb474e64c9ed199919313321e46da3a531ecc7dJohan Euphrosine Daemon::Options::ShowUsage(argv[0]); 1673fb474e64c9ed199919313321e46da3a531ecc7dJohan Euphrosine return 1; 1683fb474e64c9ed199919313321e46da3a531ecc7dJohan Euphrosine } 1693fb474e64c9ed199919313321e46da3a531ecc7dJohan Euphrosine Daemon daemon{opts}; 1703fb474e64c9ed199919313321e46da3a531ecc7dJohan Euphrosine SampleHandler handler{daemon.GetTaskRunner()}; 1713fb474e64c9ed199919313321e46da3a531ecc7dJohan Euphrosine handler.Register(daemon.GetDevice()); 1723fb474e64c9ed199919313321e46da3a531ecc7dJohan Euphrosine daemon.Run(); 1733fb474e64c9ed199919313321e46da3a531ecc7dJohan Euphrosine return 0; 1743fb474e64c9ed199919313321e46da3a531ecc7dJohan Euphrosine} 175