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