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 #ifndef LIBWEAVE_SRC_COMPONENT_MANAGER_H_ 6 #define LIBWEAVE_SRC_COMPONENT_MANAGER_H_ 7 8 #include <map> 9 #include <memory> 10 11 #include <base/callback_list.h> 12 #include <base/time/clock.h> 13 #include <base/values.h> 14 #include <weave/error.h> 15 16 #include "src/commands/command_queue.h" 17 18 namespace weave { 19 20 class CommandInstance; 21 22 enum class UserRole { 23 kViewer, 24 kUser, 25 kManager, 26 kOwner, 27 }; 28 29 // A simple notification record event to track component state changes. 30 // The |timestamp| records the time of the state change. 31 // |changed_properties| contains a property set with the new property values 32 // which were updated at the time the event was recorded. 33 struct ComponentStateChange { ComponentStateChangeComponentStateChange34 ComponentStateChange(base::Time time, 35 const std::string& path, 36 std::unique_ptr<base::DictionaryValue> properties) 37 : timestamp{time}, 38 component{path}, 39 changed_properties{std::move(properties)} {} 40 base::Time timestamp; 41 std::string component; 42 std::unique_ptr<base::DictionaryValue> changed_properties; 43 }; 44 45 class ComponentManager { 46 public: 47 using UpdateID = uint64_t; 48 using Token = 49 std::unique_ptr<base::CallbackList<void(UpdateID)>::Subscription>; 50 struct StateSnapshot { 51 UpdateID update_id; 52 std::vector<ComponentStateChange> state_changes; 53 }; 54 ComponentManager()55 ComponentManager() {} ~ComponentManager()56 virtual ~ComponentManager() {} 57 58 // Loads trait definition schema. 59 virtual bool LoadTraits(const base::DictionaryValue& dict, 60 ErrorPtr* error) = 0; 61 62 // Same as the overload above, but takes a json string to read the trait 63 // definitions from. 64 virtual bool LoadTraits(const std::string& json, ErrorPtr* error) = 0; 65 66 // Sets callback which is called when new trait definitions are added. 67 virtual void AddTraitDefChangedCallback(const base::Closure& callback) = 0; 68 69 // Adds a new component instance to device. 70 // |path| is a path to the parent component (or empty string if a root-level 71 // component is being added). 72 // |name| is a component name being added. 73 // |traits| is a list of trait names this component supports. 74 virtual bool AddComponent(const std::string& path, 75 const std::string& name, 76 const std::vector<std::string>& traits, 77 ErrorPtr* error) = 0; 78 79 // Adds a new component instance to device, as a part of component array. 80 // |path| is a path to the parent component. 81 // |name| is an array root element inside the child components. 82 // |traits| is a list of trait names this component supports. 83 virtual bool AddComponentArrayItem(const std::string& path, 84 const std::string& name, 85 const std::vector<std::string>& traits, 86 ErrorPtr* error) = 0; 87 88 // Removes an existing component instance from device. 89 // |path| is a path to the parent component (or empty string if a root-level 90 // component is being removed). 91 // |name| is a name of the component to be removed. 92 virtual bool RemoveComponent(const std::string& path, 93 const std::string& name, 94 ErrorPtr* error) = 0; 95 96 // Removes an element from component array. 97 // |path| is a path to the parent component. 98 // |index| is a zero-based element index in the component array. 99 virtual bool RemoveComponentArrayItem(const std::string& path, 100 const std::string& name, 101 size_t index, 102 ErrorPtr* error) = 0; 103 104 // Sets callback which is called when new components are added. 105 virtual void AddComponentTreeChangedCallback( 106 const base::Closure& callback) = 0; 107 108 // Adds a new command instance to the command queue. The command specified in 109 // |command_instance| must be fully initialized and have its name, component, 110 // id populated. 111 virtual void 112 AddCommand(std::unique_ptr<CommandInstance> command_instance) = 0; 113 114 // Parses the command definition from a json dictionary. The resulting command 115 // instance is populated with all the required fields and partially validated 116 // against syntax/schema. 117 // The new command ID is returned through optional |id| param. 118 virtual std::unique_ptr<CommandInstance> ParseCommandInstance( 119 const base::DictionaryValue& command, 120 Command::Origin command_origin, 121 UserRole role, 122 std::string* id, 123 ErrorPtr* error) = 0; 124 125 // Find a command instance with the given ID in the command queue. 126 virtual CommandInstance* FindCommand(const std::string& id) = 0; 127 128 // Command queue monitoring callbacks (called when a new command is added to 129 // or removed from the queue). 130 virtual void AddCommandAddedCallback( 131 const CommandQueue::CommandCallback& callback) = 0; 132 virtual void AddCommandRemovedCallback( 133 const CommandQueue::CommandCallback& callback) = 0; 134 135 // Adds a command handler for specific component's command. 136 // |component_path| is a path to target component (e.g. "stove.burners[2]"). 137 // |command_name| is a full path of the command, including trait name and 138 // command name (e.g. "burner.setPower"). 139 virtual void AddCommandHandler( 140 const std::string& component_path, 141 const std::string& command_name, 142 const Device::CommandHandlerCallback& callback) = 0; 143 144 // Finds a component instance by its full path. 145 virtual const base::DictionaryValue* FindComponent(const std::string& path, 146 ErrorPtr* error) const = 0; 147 // Finds a definition of trait with the given |name|. 148 virtual const base::DictionaryValue* FindTraitDefinition( 149 const std::string& name) const = 0; 150 151 // Finds a command definition, where |command_name| is in the form of 152 // "trait.command". 153 virtual const base::DictionaryValue* FindCommandDefinition( 154 const std::string& command_name) const = 0; 155 156 // Checks the minimum required user role for a given command. 157 virtual bool GetMinimalRole(const std::string& command_name, 158 UserRole* minimal_role, 159 ErrorPtr* error) const = 0; 160 161 // Returns the full JSON dictionary containing trait definitions. 162 virtual const base::DictionaryValue& GetTraits() const = 0; 163 164 // Returns the full JSON dictionary containing component instances. 165 virtual const base::DictionaryValue& GetComponents() const = 0; 166 167 // Component state manipulation methods. 168 virtual bool SetStateProperties(const std::string& component_path, 169 const base::DictionaryValue& dict, 170 ErrorPtr* error) = 0; 171 virtual bool SetStatePropertiesFromJson(const std::string& component_path, 172 const std::string& json, 173 ErrorPtr* error) = 0; 174 virtual const base::Value* GetStateProperty(const std::string& component_path, 175 const std::string& name, 176 ErrorPtr* error) const = 0; 177 virtual bool SetStateProperty(const std::string& component_path, 178 const std::string& name, 179 const base::Value& value, 180 ErrorPtr* error) = 0; 181 182 virtual void AddStateChangedCallback(const base::Closure& callback) = 0; 183 184 // Returns the recorded state changes since last time this method was called. 185 virtual StateSnapshot GetAndClearRecordedStateChanges() = 0; 186 187 // Called to notify that the state patch with |id| has been successfully sent 188 // to the server and processed. 189 virtual void NotifyStateUpdatedOnServer(UpdateID id) = 0; 190 191 // Returns an ID of last state change update. Each SetStatePropertyNNN() 192 // invocation increments this value by 1. 193 virtual UpdateID GetLastStateChangeId() const = 0; 194 195 // Subscribes for device state update notifications from cloud server. 196 // The |callback| will be called every time a state patch with given ID is 197 // successfully received and processed by Weave server. 198 // Returns a subscription token. As soon as this token is destroyed, the 199 // respective callback is removed from the callback list. 200 virtual Token AddServerStateUpdatedCallback( 201 const base::Callback<void(UpdateID)>& callback) = 0; 202 203 // Helper method for legacy API to obtain first component that implements 204 // the given trait. This is useful for routing commands that have no component 205 // path specified. 206 // Returns empty string if no components are found. 207 // This method only searches for component on the top level of components 208 // tree. No sub-components are searched. 209 virtual std::string FindComponentWithTrait( 210 const std::string& trait) const = 0; 211 212 // Support for legacy APIs. Setting command and state definitions. 213 // This translates into modifying a trait definition. 214 virtual bool AddLegacyCommandDefinitions(const base::DictionaryValue& dict, 215 ErrorPtr* error) = 0; 216 virtual bool AddLegacyStateDefinitions(const base::DictionaryValue& dict, 217 ErrorPtr* error) = 0; 218 // Returns device state for legacy APIs. 219 virtual const base::DictionaryValue& GetLegacyState() const = 0; 220 // Returns command definitions for legacy APIs. 221 virtual const base::DictionaryValue& GetLegacyCommandDefinitions() const = 0; 222 223 DISALLOW_COPY_AND_ASSIGN(ComponentManager); 224 }; 225 226 } // namespace weave 227 228 #endif // LIBWEAVE_SRC_COMPONENT_MANAGER_H_ 229