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 "src/base_api_handler.h"
6 
7 #include <base/bind.h>
8 #include <weave/device.h>
9 
10 #include "src/commands/schema_constants.h"
11 #include "src/device_registration_info.h"
12 
13 namespace weave {
14 
15 namespace {
16 const char kBaseComponent[] = "base";
17 const char kBaseTrait[] = "base";
18 const char kBaseStateFirmwareVersion[] = "base.firmwareVersion";
19 const char kBaseStateAnonymousAccessRole[] = "base.localAnonymousAccessMaxRole";
20 const char kBaseStateDiscoveryEnabled[] = "base.localDiscoveryEnabled";
21 const char kBaseStatePairingEnabled[] = "base.localPairingEnabled";
22 }  // namespace
23 
BaseApiHandler(DeviceRegistrationInfo * device_info,Device * device)24 BaseApiHandler::BaseApiHandler(DeviceRegistrationInfo* device_info,
25                                Device* device)
26     : device_info_{device_info}, device_{device} {
27   device_->AddTraitDefinitionsFromJson(R"({
28     "base": {
29       "commands": {
30         "updateBaseConfiguration": {
31           "minimalRole": "manager",
32           "parameters": {
33             "localAnonymousAccessMaxRole": {
34               "enum": [ "none", "viewer", "user" ],
35               "type": "string"
36             },
37             "localDiscoveryEnabled": {
38               "type": "boolean"
39             },
40             "localPairingEnabled": {
41               "type": "boolean"
42             }
43           }
44         },
45         "updateDeviceInfo": {
46           "minimalRole": "manager",
47           "parameters": {
48             "description": {
49               "type": "string"
50             },
51             "location": {
52               "type": "string"
53             },
54             "name": {
55               "type": "string"
56             }
57           }
58         },
59         "reboot": {
60           "minimalRole": "user",
61           "parameters": {},
62           "errors": ["notEnoughBattery"]
63         },
64         "identify": {
65           "minimalRole": "user",
66           "parameters": {}
67         }
68       },
69       "state": {
70         "firmwareVersion": {
71           "type": "string",
72           "isRequired": true
73         },
74         "localDiscoveryEnabled": {
75           "type": "boolean",
76           "isRequired": true
77         },
78         "localAnonymousAccessMaxRole": {
79           "type": "string",
80           "enum": [ "none", "viewer", "user" ],
81         "isRequired": true
82         },
83         "localPairingEnabled": {
84           "type": "boolean",
85           "isRequired": true
86         },
87         "connectionStatus": {
88           "type": "string"
89         },
90         "network": {
91           "type": "object",
92           "additionalProperties": false,
93           "properties": {
94             "name": { "type": "string" }
95           }
96         }
97       }
98     }
99   })");
100   CHECK(device_->AddComponent(kBaseComponent, {kBaseTrait}, nullptr));
101   OnConfigChanged(device_->GetSettings());
102 
103   const auto& settings = device_info_->GetSettings();
104   base::DictionaryValue state;
105   state.SetString(kBaseStateFirmwareVersion, settings.firmware_version);
106   CHECK(device_->SetStateProperty(kBaseComponent, kBaseStateFirmwareVersion,
107                                   base::StringValue{settings.firmware_version},
108                                   nullptr));
109 
110   device_->AddCommandHandler(
111       kBaseComponent, "base.updateBaseConfiguration",
112       base::Bind(&BaseApiHandler::UpdateBaseConfiguration,
113                  weak_ptr_factory_.GetWeakPtr()));
114 
115   device_->AddCommandHandler(kBaseComponent, "base.updateDeviceInfo",
116                              base::Bind(&BaseApiHandler::UpdateDeviceInfo,
117                                         weak_ptr_factory_.GetWeakPtr()));
118 
119   device_info_->GetMutableConfig()->AddOnChangedCallback(base::Bind(
120       &BaseApiHandler::OnConfigChanged, weak_ptr_factory_.GetWeakPtr()));
121 }
122 
UpdateBaseConfiguration(const std::weak_ptr<Command> & cmd)123 void BaseApiHandler::UpdateBaseConfiguration(
124     const std::weak_ptr<Command>& cmd) {
125   auto command = cmd.lock();
126   if (!command)
127     return;
128   CHECK(command->GetState() == Command::State::kQueued)
129       << EnumToString(command->GetState());
130   command->SetProgress(base::DictionaryValue{}, nullptr);
131 
132   const auto& settings = device_info_->GetSettings();
133   std::string anonymous_access_role{
134       EnumToString(settings.local_anonymous_access_role)};
135   bool discovery_enabled{settings.local_discovery_enabled};
136   bool pairing_enabled{settings.local_pairing_enabled};
137 
138   const auto& parameters = command->GetParameters();
139   parameters.GetString("localAnonymousAccessMaxRole", &anonymous_access_role);
140   parameters.GetBoolean("localDiscoveryEnabled", &discovery_enabled);
141   parameters.GetBoolean("localPairingEnabled", &pairing_enabled);
142 
143   AuthScope auth_scope{AuthScope::kNone};
144   if (!StringToEnum(anonymous_access_role, &auth_scope)) {
145     ErrorPtr error;
146     Error::AddToPrintf(&error, FROM_HERE, errors::commands::kInvalidPropValue,
147                        "Invalid localAnonymousAccessMaxRole value '%s'",
148                        anonymous_access_role.c_str());
149     command->Abort(error.get(), nullptr);
150     return;
151   }
152 
153   device_info_->UpdateBaseConfig(auth_scope, discovery_enabled,
154                                  pairing_enabled);
155 
156   command->Complete({}, nullptr);
157 }
158 
OnConfigChanged(const Settings & settings)159 void BaseApiHandler::OnConfigChanged(const Settings& settings) {
160   base::DictionaryValue state;
161   state.SetString(kBaseStateAnonymousAccessRole,
162                   EnumToString(settings.local_anonymous_access_role));
163   state.SetBoolean(kBaseStateDiscoveryEnabled,
164                    settings.local_discovery_enabled);
165   state.SetBoolean(kBaseStatePairingEnabled, settings.local_pairing_enabled);
166   device_->SetStateProperties(kBaseComponent, state, nullptr);
167 }
168 
UpdateDeviceInfo(const std::weak_ptr<Command> & cmd)169 void BaseApiHandler::UpdateDeviceInfo(const std::weak_ptr<Command>& cmd) {
170   auto command = cmd.lock();
171   if (!command)
172     return;
173   CHECK(command->GetState() == Command::State::kQueued)
174       << EnumToString(command->GetState());
175   command->SetProgress(base::DictionaryValue{}, nullptr);
176 
177   const auto& settings = device_info_->GetSettings();
178   std::string name{settings.name};
179   std::string description{settings.description};
180   std::string location{settings.location};
181 
182   const auto& parameters = command->GetParameters();
183   parameters.GetString("name", &name);
184   parameters.GetString("description", &description);
185   parameters.GetString("location", &location);
186 
187   device_info_->UpdateDeviceInfo(name, description, location);
188   command->Complete({}, nullptr);
189 }
190 
191 }  // namespace weave
192