| // Copyright 2015 The Weave Authors. All rights reserved. | 
 | // Use of this source code is governed by a BSD-style license that can be | 
 | // found in the LICENSE file. | 
 |  | 
 | #include "src/base_api_handler.h" | 
 |  | 
 | #include <base/bind.h> | 
 | #include <weave/device.h> | 
 |  | 
 | #include "src/commands/schema_constants.h" | 
 | #include "src/device_registration_info.h" | 
 |  | 
 | namespace weave { | 
 |  | 
 | namespace { | 
 | const char kBaseComponent[] = "base"; | 
 | const char kBaseTrait[] = "base"; | 
 | const char kBaseStateFirmwareVersion[] = "base.firmwareVersion"; | 
 | const char kBaseStateAnonymousAccessRole[] = "base.localAnonymousAccessMaxRole"; | 
 | const char kBaseStateDiscoveryEnabled[] = "base.localDiscoveryEnabled"; | 
 | const char kBaseStatePairingEnabled[] = "base.localPairingEnabled"; | 
 | }  // namespace | 
 |  | 
 | BaseApiHandler::BaseApiHandler(DeviceRegistrationInfo* device_info, | 
 |                                Device* device) | 
 |     : device_info_{device_info}, device_{device} { | 
 |   device_->AddTraitDefinitionsFromJson(R"({ | 
 |     "base": { | 
 |       "commands": { | 
 |         "updateBaseConfiguration": { | 
 |           "minimalRole": "manager", | 
 |           "parameters": { | 
 |             "localAnonymousAccessMaxRole": { | 
 |               "enum": [ "none", "viewer", "user" ], | 
 |               "type": "string" | 
 |             }, | 
 |             "localDiscoveryEnabled": { | 
 |               "type": "boolean" | 
 |             }, | 
 |             "localPairingEnabled": { | 
 |               "type": "boolean" | 
 |             } | 
 |           } | 
 |         }, | 
 |         "updateDeviceInfo": { | 
 |           "minimalRole": "manager", | 
 |           "parameters": { | 
 |             "description": { | 
 |               "type": "string" | 
 |             }, | 
 |             "location": { | 
 |               "type": "string" | 
 |             }, | 
 |             "name": { | 
 |               "type": "string" | 
 |             } | 
 |           } | 
 |         }, | 
 |         "reboot": { | 
 |           "minimalRole": "user", | 
 |           "parameters": {}, | 
 |           "errors": ["notEnoughBattery"] | 
 |         }, | 
 |         "identify": { | 
 |           "minimalRole": "user", | 
 |           "parameters": {} | 
 |         } | 
 |       }, | 
 |       "state": { | 
 |         "firmwareVersion": { | 
 |           "type": "string", | 
 |           "isRequired": true | 
 |         }, | 
 |         "localDiscoveryEnabled": { | 
 |           "type": "boolean", | 
 |           "isRequired": true | 
 |         }, | 
 |         "localAnonymousAccessMaxRole": { | 
 |           "type": "string", | 
 |           "enum": [ "none", "viewer", "user" ], | 
 |         "isRequired": true | 
 |         }, | 
 |         "localPairingEnabled": { | 
 |           "type": "boolean", | 
 |           "isRequired": true | 
 |         }, | 
 |         "connectionStatus": { | 
 |           "type": "string" | 
 |         }, | 
 |         "network": { | 
 |           "type": "object", | 
 |           "additionalProperties": false, | 
 |           "properties": { | 
 |             "name": { "type": "string" } | 
 |           } | 
 |         } | 
 |       } | 
 |     } | 
 |   })"); | 
 |   CHECK(device_->AddComponent(kBaseComponent, {kBaseTrait}, nullptr)); | 
 |   OnConfigChanged(device_->GetSettings()); | 
 |  | 
 |   const auto& settings = device_info_->GetSettings(); | 
 |   base::DictionaryValue state; | 
 |   state.SetString(kBaseStateFirmwareVersion, settings.firmware_version); | 
 |   CHECK(device_->SetStateProperty(kBaseComponent, kBaseStateFirmwareVersion, | 
 |                                   base::StringValue{settings.firmware_version}, | 
 |                                   nullptr)); | 
 |  | 
 |   device_->AddCommandHandler( | 
 |       kBaseComponent, "base.updateBaseConfiguration", | 
 |       base::Bind(&BaseApiHandler::UpdateBaseConfiguration, | 
 |                  weak_ptr_factory_.GetWeakPtr())); | 
 |  | 
 |   device_->AddCommandHandler(kBaseComponent, "base.updateDeviceInfo", | 
 |                              base::Bind(&BaseApiHandler::UpdateDeviceInfo, | 
 |                                         weak_ptr_factory_.GetWeakPtr())); | 
 |  | 
 |   device_info_->GetMutableConfig()->AddOnChangedCallback(base::Bind( | 
 |       &BaseApiHandler::OnConfigChanged, weak_ptr_factory_.GetWeakPtr())); | 
 | } | 
 |  | 
 | void BaseApiHandler::UpdateBaseConfiguration( | 
 |     const std::weak_ptr<Command>& cmd) { | 
 |   auto command = cmd.lock(); | 
 |   if (!command) | 
 |     return; | 
 |   CHECK(command->GetState() == Command::State::kQueued) | 
 |       << EnumToString(command->GetState()); | 
 |   command->SetProgress(base::DictionaryValue{}, nullptr); | 
 |  | 
 |   const auto& settings = device_info_->GetSettings(); | 
 |   std::string anonymous_access_role{ | 
 |       EnumToString(settings.local_anonymous_access_role)}; | 
 |   bool discovery_enabled{settings.local_discovery_enabled}; | 
 |   bool pairing_enabled{settings.local_pairing_enabled}; | 
 |  | 
 |   const auto& parameters = command->GetParameters(); | 
 |   parameters.GetString("localAnonymousAccessMaxRole", &anonymous_access_role); | 
 |   parameters.GetBoolean("localDiscoveryEnabled", &discovery_enabled); | 
 |   parameters.GetBoolean("localPairingEnabled", &pairing_enabled); | 
 |  | 
 |   AuthScope auth_scope{AuthScope::kNone}; | 
 |   if (!StringToEnum(anonymous_access_role, &auth_scope)) { | 
 |     ErrorPtr error; | 
 |     Error::AddToPrintf(&error, FROM_HERE, errors::commands::kInvalidPropValue, | 
 |                        "Invalid localAnonymousAccessMaxRole value '%s'", | 
 |                        anonymous_access_role.c_str()); | 
 |     command->Abort(error.get(), nullptr); | 
 |     return; | 
 |   } | 
 |  | 
 |   device_info_->UpdateBaseConfig(auth_scope, discovery_enabled, | 
 |                                  pairing_enabled); | 
 |  | 
 |   command->Complete({}, nullptr); | 
 | } | 
 |  | 
 | void BaseApiHandler::OnConfigChanged(const Settings& settings) { | 
 |   base::DictionaryValue state; | 
 |   state.SetString(kBaseStateAnonymousAccessRole, | 
 |                   EnumToString(settings.local_anonymous_access_role)); | 
 |   state.SetBoolean(kBaseStateDiscoveryEnabled, | 
 |                    settings.local_discovery_enabled); | 
 |   state.SetBoolean(kBaseStatePairingEnabled, settings.local_pairing_enabled); | 
 |   device_->SetStateProperties(kBaseComponent, state, nullptr); | 
 | } | 
 |  | 
 | void BaseApiHandler::UpdateDeviceInfo(const std::weak_ptr<Command>& cmd) { | 
 |   auto command = cmd.lock(); | 
 |   if (!command) | 
 |     return; | 
 |   CHECK(command->GetState() == Command::State::kQueued) | 
 |       << EnumToString(command->GetState()); | 
 |   command->SetProgress(base::DictionaryValue{}, nullptr); | 
 |  | 
 |   const auto& settings = device_info_->GetSettings(); | 
 |   std::string name{settings.name}; | 
 |   std::string description{settings.description}; | 
 |   std::string location{settings.location}; | 
 |  | 
 |   const auto& parameters = command->GetParameters(); | 
 |   parameters.GetString("name", &name); | 
 |   parameters.GetString("description", &description); | 
 |   parameters.GetString("location", &location); | 
 |  | 
 |   device_info_->UpdateDeviceInfo(name, description, location); | 
 |   command->Complete({}, nullptr); | 
 | } | 
 |  | 
 | }  // namespace weave |