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 
13 namespace weave {
14 namespace lockstate {
15 enum class LockState { kUnlocked, kLocked, kPartiallyLocked };
16 
17 const weave::EnumToStringMap<LockState>::Map kLockMapMethod[] = {
18     {LockState::kLocked, "locked"},
19     {LockState::kUnlocked, "unlocked"},
20     {LockState::kPartiallyLocked, "partiallyLocked"}};
21 }  // namespace lockstate
22 
23 template <>
EnumToStringMap()24 EnumToStringMap<lockstate::LockState>::EnumToStringMap()
25     : EnumToStringMap(lockstate::kLockMapMethod) {}
26 }  // namespace weave
27 
28 namespace {
29 
30 const 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 
58 const char kDefaultState[] = R"({
59   "lock":{"isLockingSupported": true}
60 })";
61 
62 const 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.
68 class LockHandler {
69  public:
70   LockHandler() = default;
Register(weave::Device * device)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:
OnLockSetConfig(const std::weak_ptr<weave::Command> & command)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 
UpdateLockState()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 
main(int argc,char ** argv)135 int 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