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