1c18c7cfe350a5e671deaf1c2eaa30868e6ceb67fPaul Westbrook// Copyright 2015 The Weave Authors. All rights reserved. 2c18c7cfe350a5e671deaf1c2eaa30868e6ceb67fPaul Westbrook// Use of this source code is governed by a BSD-style license that can be 3c18c7cfe350a5e671deaf1c2eaa30868e6ceb67fPaul Westbrook// found in the LICENSE file. 4c18c7cfe350a5e671deaf1c2eaa30868e6ceb67fPaul Westbrook 53fb474e64c9ed199919313321e46da3a531ecc7dJohan Euphrosine#include "examples/daemon/common/daemon.h" 63fb474e64c9ed199919313321e46da3a531ecc7dJohan Euphrosine 7c18c7cfe350a5e671deaf1c2eaa30868e6ceb67fPaul Westbrook#include <weave/device.h> 8c18c7cfe350a5e671deaf1c2eaa30868e6ceb67fPaul Westbrook#include <weave/enum_to_string.h> 9c18c7cfe350a5e671deaf1c2eaa30868e6ceb67fPaul Westbrook 10c18c7cfe350a5e671deaf1c2eaa30868e6ceb67fPaul Westbrook#include <base/bind.h> 11c18c7cfe350a5e671deaf1c2eaa30868e6ceb67fPaul Westbrook#include <base/memory/weak_ptr.h> 12c18c7cfe350a5e671deaf1c2eaa30868e6ceb67fPaul Westbrook 13c18c7cfe350a5e671deaf1c2eaa30868e6ceb67fPaul Westbrooknamespace weave { 14c18c7cfe350a5e671deaf1c2eaa30868e6ceb67fPaul Westbrooknamespace lockstate { 15c18c7cfe350a5e671deaf1c2eaa30868e6ceb67fPaul Westbrookenum class LockState { kUnlocked, kLocked, kPartiallyLocked }; 16c18c7cfe350a5e671deaf1c2eaa30868e6ceb67fPaul Westbrook 17c18c7cfe350a5e671deaf1c2eaa30868e6ceb67fPaul Westbrookconst weave::EnumToStringMap<LockState>::Map kLockMapMethod[] = { 183fb474e64c9ed199919313321e46da3a531ecc7dJohan Euphrosine {LockState::kLocked, "locked"}, 193fb474e64c9ed199919313321e46da3a531ecc7dJohan Euphrosine {LockState::kUnlocked, "unlocked"}, 203fb474e64c9ed199919313321e46da3a531ecc7dJohan Euphrosine {LockState::kPartiallyLocked, "partiallyLocked"}}; 21c18c7cfe350a5e671deaf1c2eaa30868e6ceb67fPaul Westbrook} // namespace lockstate 22c18c7cfe350a5e671deaf1c2eaa30868e6ceb67fPaul Westbrook 23c18c7cfe350a5e671deaf1c2eaa30868e6ceb67fPaul Westbrooktemplate <> 24c18c7cfe350a5e671deaf1c2eaa30868e6ceb67fPaul WestbrookEnumToStringMap<lockstate::LockState>::EnumToStringMap() 253fb474e64c9ed199919313321e46da3a531ecc7dJohan Euphrosine : EnumToStringMap(lockstate::kLockMapMethod) {} 263fb474e64c9ed199919313321e46da3a531ecc7dJohan Euphrosine} // namespace weave 27c18c7cfe350a5e671deaf1c2eaa30868e6ceb67fPaul Westbrook 28d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenkonamespace { 29d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko 30d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenkoconst char kTraits[] = R"({ 31d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko "lock": { 32d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko "commands": { 33d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko "setConfig": { 34d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko "minimalRole": "user", 35d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko "parameters": { 36d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko "lockedState": { 37d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko "type": "string", 38d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko "enum": [ "locked", "unlocked" ] 39d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko } 408d0cfefae24985025a934ea5461a51472c59cfc0Alex Vakulenko }, 418d0cfefae24985025a934ea5461a51472c59cfc0Alex Vakulenko "errors": ["batteryTooLow", "jammed", "lockingNotSupported"] 42d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko } 43d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko }, 44d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko "state": { 45d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko "lockedState": { 46d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko "type": "string", 478d0cfefae24985025a934ea5461a51472c59cfc0Alex Vakulenko "enum": [ "locked", "unlocked", "partiallyLocked" ], 488d0cfefae24985025a934ea5461a51472c59cfc0Alex Vakulenko "isRequired": true 49d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko }, 508d0cfefae24985025a934ea5461a51472c59cfc0Alex Vakulenko "isLockingSupported": { 518d0cfefae24985025a934ea5461a51472c59cfc0Alex Vakulenko "type": "boolean", 528d0cfefae24985025a934ea5461a51472c59cfc0Alex Vakulenko "isRequired": true 538d0cfefae24985025a934ea5461a51472c59cfc0Alex Vakulenko } 54d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko } 55d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko } 56d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko})"; 57d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko 58d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenkoconst char kDefaultState[] = R"({ 59d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko "lock":{"isLockingSupported": true} 60d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko})"; 61d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko 62d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenkoconst char kComponent[] = "lock"; 63d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko 64d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko} // anonymous namespace 65d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko 66c18c7cfe350a5e671deaf1c2eaa30868e6ceb67fPaul Westbrook// LockHandler is a command handler example that shows 67c18c7cfe350a5e671deaf1c2eaa30868e6ceb67fPaul Westbrook// how to handle commands for a Weave lock. 68c18c7cfe350a5e671deaf1c2eaa30868e6ceb67fPaul Westbrookclass LockHandler { 69c18c7cfe350a5e671deaf1c2eaa30868e6ceb67fPaul Westbrook public: 70c18c7cfe350a5e671deaf1c2eaa30868e6ceb67fPaul Westbrook LockHandler() = default; 713fb474e64c9ed199919313321e46da3a531ecc7dJohan Euphrosine void Register(weave::Device* device) { 72c18c7cfe350a5e671deaf1c2eaa30868e6ceb67fPaul Westbrook device_ = device; 73c18c7cfe350a5e671deaf1c2eaa30868e6ceb67fPaul Westbrook 74d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko device->AddTraitDefinitionsFromJson(kTraits); 75d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko CHECK(device->AddComponent(kComponent, {"lock"}, nullptr)); 7634668e731bb194b443bc0e6029d6d3583f08de28Vitaly Buka CHECK( 7734668e731bb194b443bc0e6029d6d3583f08de28Vitaly Buka device->SetStatePropertiesFromJson(kComponent, kDefaultState, nullptr)); 78d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko UpdateLockState(); 79c18c7cfe350a5e671deaf1c2eaa30868e6ceb67fPaul Westbrook 80d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko device->AddCommandHandler(kComponent, "lock.setConfig", 813fb474e64c9ed199919313321e46da3a531ecc7dJohan Euphrosine base::Bind(&LockHandler::OnLockSetConfig, 823fb474e64c9ed199919313321e46da3a531ecc7dJohan Euphrosine weak_ptr_factory_.GetWeakPtr())); 83c18c7cfe350a5e671deaf1c2eaa30868e6ceb67fPaul Westbrook } 84c18c7cfe350a5e671deaf1c2eaa30868e6ceb67fPaul Westbrook 85c18c7cfe350a5e671deaf1c2eaa30868e6ceb67fPaul Westbrook private: 863fb474e64c9ed199919313321e46da3a531ecc7dJohan Euphrosine void OnLockSetConfig(const std::weak_ptr<weave::Command>& command) { 87c18c7cfe350a5e671deaf1c2eaa30868e6ceb67fPaul Westbrook auto cmd = command.lock(); 88c18c7cfe350a5e671deaf1c2eaa30868e6ceb67fPaul Westbrook if (!cmd) 89c18c7cfe350a5e671deaf1c2eaa30868e6ceb67fPaul Westbrook return; 90c18c7cfe350a5e671deaf1c2eaa30868e6ceb67fPaul Westbrook LOG(INFO) << "received command: " << cmd->GetName(); 91c4305600835b91630f9ca4b10ad9070ea55a726cVitaly Buka const auto& params = cmd->GetParameters(); 92c18c7cfe350a5e671deaf1c2eaa30868e6ceb67fPaul Westbrook std::string requested_state; 93c4305600835b91630f9ca4b10ad9070ea55a726cVitaly Buka if (params.GetString("lockedState", &requested_state)) { 94c18c7cfe350a5e671deaf1c2eaa30868e6ceb67fPaul Westbrook LOG(INFO) << cmd->GetName() << " state: " << requested_state; 95c18c7cfe350a5e671deaf1c2eaa30868e6ceb67fPaul Westbrook 963fb474e64c9ed199919313321e46da3a531ecc7dJohan Euphrosine weave::lockstate::LockState new_lock_status; 97c18c7cfe350a5e671deaf1c2eaa30868e6ceb67fPaul Westbrook 98c18c7cfe350a5e671deaf1c2eaa30868e6ceb67fPaul Westbrook if (!weave::StringToEnum(requested_state, &new_lock_status)) { 99c18c7cfe350a5e671deaf1c2eaa30868e6ceb67fPaul Westbrook // Invalid lock state was specified. 1003fb474e64c9ed199919313321e46da3a531ecc7dJohan Euphrosine weave::ErrorPtr error; 10148a8669ddc2e8d785aad9ad18a5abbf8f1224fdeVitaly Buka weave::Error::AddTo(&error, FROM_HERE, "invalid_parameter_value", 10248a8669ddc2e8d785aad9ad18a5abbf8f1224fdeVitaly Buka "Invalid parameters"); 103c18c7cfe350a5e671deaf1c2eaa30868e6ceb67fPaul Westbrook cmd->Abort(error.get(), nullptr); 104c18c7cfe350a5e671deaf1c2eaa30868e6ceb67fPaul Westbrook return; 105c18c7cfe350a5e671deaf1c2eaa30868e6ceb67fPaul Westbrook } 106c18c7cfe350a5e671deaf1c2eaa30868e6ceb67fPaul Westbrook 107c18c7cfe350a5e671deaf1c2eaa30868e6ceb67fPaul Westbrook if (new_lock_status != lock_state_) { 108c18c7cfe350a5e671deaf1c2eaa30868e6ceb67fPaul Westbrook lock_state_ = new_lock_status; 109c18c7cfe350a5e671deaf1c2eaa30868e6ceb67fPaul Westbrook 110c18c7cfe350a5e671deaf1c2eaa30868e6ceb67fPaul Westbrook LOG(INFO) << "Lock is now: " << requested_state; 111c18c7cfe350a5e671deaf1c2eaa30868e6ceb67fPaul Westbrook UpdateLockState(); 112c18c7cfe350a5e671deaf1c2eaa30868e6ceb67fPaul Westbrook } 113c18c7cfe350a5e671deaf1c2eaa30868e6ceb67fPaul Westbrook cmd->Complete({}, nullptr); 114c18c7cfe350a5e671deaf1c2eaa30868e6ceb67fPaul Westbrook return; 115c18c7cfe350a5e671deaf1c2eaa30868e6ceb67fPaul Westbrook } 1163fb474e64c9ed199919313321e46da3a531ecc7dJohan Euphrosine weave::ErrorPtr error; 11748a8669ddc2e8d785aad9ad18a5abbf8f1224fdeVitaly Buka weave::Error::AddTo(&error, FROM_HERE, "invalid_parameter_value", 1183fb474e64c9ed199919313321e46da3a531ecc7dJohan Euphrosine "Invalid parameters"); 119c18c7cfe350a5e671deaf1c2eaa30868e6ceb67fPaul Westbrook cmd->Abort(error.get(), nullptr); 120c18c7cfe350a5e671deaf1c2eaa30868e6ceb67fPaul Westbrook } 121c18c7cfe350a5e671deaf1c2eaa30868e6ceb67fPaul Westbrook 1223fb474e64c9ed199919313321e46da3a531ecc7dJohan Euphrosine void UpdateLockState() { 123c18c7cfe350a5e671deaf1c2eaa30868e6ceb67fPaul Westbrook std::string updated_state = weave::EnumToString(lock_state_); 124d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko device_->SetStateProperty(kComponent, "lock.lockedState", 125d6db0498402a32ef8ff5b681cef555e4c4fc2079Alex Vakulenko base::StringValue{updated_state}, nullptr); 126c18c7cfe350a5e671deaf1c2eaa30868e6ceb67fPaul Westbrook } 127c18c7cfe350a5e671deaf1c2eaa30868e6ceb67fPaul Westbrook 1283fb474e64c9ed199919313321e46da3a531ecc7dJohan Euphrosine weave::Device* device_{nullptr}; 129c18c7cfe350a5e671deaf1c2eaa30868e6ceb67fPaul Westbrook 130c18c7cfe350a5e671deaf1c2eaa30868e6ceb67fPaul Westbrook // Simulate the state of the light. 1313fb474e64c9ed199919313321e46da3a531ecc7dJohan Euphrosine weave::lockstate::LockState lock_state_{weave::lockstate::LockState::kLocked}; 132c18c7cfe350a5e671deaf1c2eaa30868e6ceb67fPaul Westbrook base::WeakPtrFactory<LockHandler> weak_ptr_factory_{this}; 133c18c7cfe350a5e671deaf1c2eaa30868e6ceb67fPaul Westbrook}; 134c18c7cfe350a5e671deaf1c2eaa30868e6ceb67fPaul Westbrook 1353fb474e64c9ed199919313321e46da3a531ecc7dJohan Euphrosineint main(int argc, char** argv) { 1363fb474e64c9ed199919313321e46da3a531ecc7dJohan Euphrosine Daemon::Options opts; 13704e628f7854b7252ccda1b303a8e99d840cf9a98Paul Westbrook opts.model_id_ = "AOAAA"; 1383fb474e64c9ed199919313321e46da3a531ecc7dJohan Euphrosine if (!opts.Parse(argc, argv)) { 1393fb474e64c9ed199919313321e46da3a531ecc7dJohan Euphrosine Daemon::Options::ShowUsage(argv[0]); 1403fb474e64c9ed199919313321e46da3a531ecc7dJohan Euphrosine return 1; 1413fb474e64c9ed199919313321e46da3a531ecc7dJohan Euphrosine } 1423fb474e64c9ed199919313321e46da3a531ecc7dJohan Euphrosine Daemon daemon{opts}; 1433fb474e64c9ed199919313321e46da3a531ecc7dJohan Euphrosine LockHandler handler; 1443fb474e64c9ed199919313321e46da3a531ecc7dJohan Euphrosine handler.Register(daemon.GetDevice()); 1453fb474e64c9ed199919313321e46da3a531ecc7dJohan Euphrosine daemon.Run(); 1463fb474e64c9ed199919313321e46da3a531ecc7dJohan Euphrosine return 0; 1473fb474e64c9ed199919313321e46da3a531ecc7dJohan Euphrosine} 148