1// 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
5#include "examples/daemon/common/daemon.h"
6
7#include <weave/device.h>
8#include <weave/enum_to_string.h>
9
10#include <base/bind.h>
11#include <base/memory/weak_ptr.h>
12
13namespace weave {
14namespace lockstate {
15enum class LockState { kUnlocked, kLocked, kPartiallyLocked };
16
17const weave::EnumToStringMap<LockState>::Map kLockMapMethod[] = {
18    {LockState::kLocked, "locked"},
19    {LockState::kUnlocked, "unlocked"},
20    {LockState::kPartiallyLocked, "partiallyLocked"}};
21}  // namespace lockstate
22
23template <>
24EnumToStringMap<lockstate::LockState>::EnumToStringMap()
25    : EnumToStringMap(lockstate::kLockMapMethod) {}
26}  // namespace weave
27
28namespace {
29
30const char kTraits[] = R"({
31  "lock": {
32    "commands": {
33      "setConfig": {
34        "minimalRole": "user",
35        "parameters": {
36          "lockedState": {
37            "type": "string",
38            "enum": [ "locked", "unlocked" ]
39          }
40        },
41        "errors": ["batteryTooLow", "jammed", "lockingNotSupported"]
42      }
43    },
44    "state": {
45      "lockedState": {
46        "type": "string",
47        "enum": [ "locked", "unlocked", "partiallyLocked" ],
48        "isRequired": true
49      },
50      "isLockingSupported": {
51        "type": "boolean",
52        "isRequired": true
53      }
54    }
55  }
56})";
57
58const char kDefaultState[] = R"({
59  "lock":{"isLockingSupported": true}
60})";
61
62const char kComponent[] = "lock";
63
64}  // anonymous namespace
65
66// LockHandler is a command handler example that shows
67// how to handle commands for a Weave lock.
68class LockHandler {
69 public:
70  LockHandler() = default;
71  void Register(weave::Device* device) {
72    device_ = device;
73
74    device->AddTraitDefinitionsFromJson(kTraits);
75    CHECK(device->AddComponent(kComponent, {"lock"}, nullptr));
76    CHECK(
77        device->SetStatePropertiesFromJson(kComponent, kDefaultState, nullptr));
78    UpdateLockState();
79
80    device->AddCommandHandler(kComponent, "lock.setConfig",
81                              base::Bind(&LockHandler::OnLockSetConfig,
82                                         weak_ptr_factory_.GetWeakPtr()));
83  }
84
85 private:
86  void OnLockSetConfig(const std::weak_ptr<weave::Command>& command) {
87    auto cmd = command.lock();
88    if (!cmd)
89      return;
90    LOG(INFO) << "received command: " << cmd->GetName();
91    const auto& params = cmd->GetParameters();
92    std::string requested_state;
93    if (params.GetString("lockedState", &requested_state)) {
94      LOG(INFO) << cmd->GetName() << " state: " << requested_state;
95
96      weave::lockstate::LockState new_lock_status;
97
98      if (!weave::StringToEnum(requested_state, &new_lock_status)) {
99        // Invalid lock state was specified.
100        weave::ErrorPtr error;
101        weave::Error::AddTo(&error, FROM_HERE, "invalid_parameter_value",
102                            "Invalid parameters");
103        cmd->Abort(error.get(), nullptr);
104        return;
105      }
106
107      if (new_lock_status != lock_state_) {
108        lock_state_ = new_lock_status;
109
110        LOG(INFO) << "Lock is now: " << requested_state;
111        UpdateLockState();
112      }
113      cmd->Complete({}, nullptr);
114      return;
115    }
116    weave::ErrorPtr error;
117    weave::Error::AddTo(&error, FROM_HERE, "invalid_parameter_value",
118                        "Invalid parameters");
119    cmd->Abort(error.get(), nullptr);
120  }
121
122  void UpdateLockState() {
123    std::string updated_state = weave::EnumToString(lock_state_);
124    device_->SetStateProperty(kComponent, "lock.lockedState",
125                              base::StringValue{updated_state}, nullptr);
126  }
127
128  weave::Device* device_{nullptr};
129
130  // Simulate the state of the light.
131  weave::lockstate::LockState lock_state_{weave::lockstate::LockState::kLocked};
132  base::WeakPtrFactory<LockHandler> weak_ptr_factory_{this};
133};
134
135int main(int argc, char** argv) {
136  Daemon::Options opts;
137  opts.model_id_ = "AOAAA";
138  if (!opts.Parse(argc, argv)) {
139    Daemon::Options::ShowUsage(argv[0]);
140    return 1;
141  }
142  Daemon daemon{opts};
143  LockHandler handler;
144  handler.Register(daemon.GetDevice());
145  daemon.Run();
146  return 0;
147}
148