blob: 6b8ff1370f187dc6d9bd0bde348e93c73c28b77f [file] [log] [blame]
Alex Vakulenkoba981152015-12-05 13:58:22 -08001// 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_IMPL_H_
6#define LIBWEAVE_SRC_COMPONENT_MANAGER_IMPL_H_
7
Vitaly Bukaece713e2015-12-09 10:59:33 -08008#include <base/time/default_clock.h>
9
Alex Vakulenkoba981152015-12-05 13:58:22 -080010#include "src/commands/command_queue.h"
11#include "src/component_manager.h"
12#include "src/states/state_change_queue.h"
13
14namespace weave {
15
16class ComponentManagerImpl final : public ComponentManager {
17 public:
Vitaly Bukaece713e2015-12-09 10:59:33 -080018 explicit ComponentManagerImpl(base::Clock* clock = nullptr);
Alex Vakulenkoba981152015-12-05 13:58:22 -080019 ~ComponentManagerImpl() override;
20
21 // Loads trait definition schema.
22 bool LoadTraits(const base::DictionaryValue& dict, ErrorPtr* error) override;
23
24 // Same as the overload above, but takes a json string to read the trait
25 // definitions from.
26 bool LoadTraits(const std::string& json, ErrorPtr* error) override;
27
28 // Sets callback which is called when new trait definitions are added.
29 void AddTraitDefChangedCallback(const base::Closure& callback) override;
30
31 // Adds a new component instance to device.
32 // |path| is a path to the parent component (or empty string if a root-level
33 // component is being added).
34 // |name| is a component name being added.
35 // |traits| is a list of trait names this component supports.
36 bool AddComponent(const std::string& path,
37 const std::string& name,
38 const std::vector<std::string>& traits,
39 ErrorPtr* error) override;
40
41 // Adds a new component instance to device, as a part of component array.
42 // |path| is a path to the parent component.
43 // |name| is an array root element inside the child components.
44 // |traits| is a list of trait names this component supports.
45 bool AddComponentArrayItem(const std::string& path,
46 const std::string& name,
47 const std::vector<std::string>& traits,
48 ErrorPtr* error) override;
49
50 // Sets callback which is called when new components are added.
51 void AddComponentTreeChangedCallback(const base::Closure& callback) override;
52
Alex Vakulenkod91d6252015-12-05 17:14:39 -080053 // Adds a new command instance to the command queue. The command specified in
54 // |command_instance| must be fully initialized and have its name, component,
55 // id populated.
56 void AddCommand(
57 std::unique_ptr<CommandInstance> command_instance) override;
58
59 // Parses the command definition from a json dictionary. The resulting command
60 // instance is populated with all the required fields and partially validated
61 // against syntax/schema.
62 // The new command ID is returned through optional |id| param.
63 std::unique_ptr<CommandInstance> ParseCommandInstance(
64 const base::DictionaryValue& command,
65 Command::Origin command_origin,
66 UserRole role,
67 std::string* id,
68 ErrorPtr* error) override;
Alex Vakulenkoba981152015-12-05 13:58:22 -080069
70 // Find a command instance with the given ID in the command queue.
71 CommandInstance* FindCommand(const std::string& id) override;
72
73 // Command queue monitoring callbacks (called when a new command is added to
74 // or removed from the queue).
75 void AddCommandAddedCallback(
76 const CommandQueue::CommandCallback& callback) override;
77 void AddCommandRemovedCallback(
78 const CommandQueue::CommandCallback& callback) override;
79
80 // Adds a command handler for specific component's command.
81 // |component_path| is a path to target component (e.g. "stove.burners[2]").
82 // |command_name| is a full path of the command, including trait name and
83 // command name (e.g. "burner.setPower").
84 void AddCommandHandler(
85 const std::string& component_path,
86 const std::string& command_name,
87 const Device::CommandHandlerCallback& callback) override;
88
89 // Finds a component instance by its full path.
90 const base::DictionaryValue* FindComponent(const std::string& path,
91 ErrorPtr* error) const override;
92 // Finds a definition of trait with the given |name|.
93 const base::DictionaryValue* FindTraitDefinition(
94 const std::string& name) const override;
95
96 // Finds a command definition, where |command_name| is in the form of
97 // "trait.command".
98 const base::DictionaryValue* FindCommandDefinition(
99 const std::string& command_name) const override;
100
101 // Checks the minimum required user role for a given command.
102 bool GetMinimalRole(const std::string& command_name,
103 UserRole* minimal_role,
104 ErrorPtr* error) const override;
105
106 // Returns the full JSON dictionary containing trait definitions.
107 const base::DictionaryValue& GetTraits() const override { return traits_; }
108
109 // Returns the full JSON dictionary containing component instances.
110 const base::DictionaryValue& GetComponents() const override {
111 return components_;
112 }
113
114 // Component state manipulation methods.
115 bool SetStateProperties(const std::string& component_path,
116 const base::DictionaryValue& dict,
117 ErrorPtr* error) override;
118 bool SetStatePropertiesFromJson(const std::string& component_path,
119 const std::string& json,
120 ErrorPtr* error) override;
121 const base::Value* GetStateProperty(const std::string& component_path,
122 const std::string& name,
123 ErrorPtr* error) const override;
124 bool SetStateProperty(const std::string& component_path,
125 const std::string& name,
126 const base::Value& value,
127 ErrorPtr* error) override;
128
129 void AddStateChangedCallback(const base::Closure& callback) override;
130
131 // Returns the recorded state changes since last time this method was called.
132 StateSnapshot GetAndClearRecordedStateChanges() override;
133
134 // Called to notify that the state patch with |id| has been successfully sent
135 // to the server and processed.
136 void NotifyStateUpdatedOnServer(UpdateID id) override;
137
138 // Returns an ID of last state change update. Each SetStatePropertyNNN()
139 // invocation increments this value by 1.
140 UpdateID GetLastStateChangeId() const override {
141 return last_state_change_id_;
142 }
143
144 // Subscribes for device state update notifications from cloud server.
145 // The |callback| will be called every time a state patch with given ID is
146 // successfully received and processed by Weave server.
147 // Returns a subscription token. As soon as this token is destroyed, the
148 // respective callback is removed from the callback list.
149 Token AddServerStateUpdatedCallback(
150 const base::Callback<void(UpdateID)>& callback) override;
151
152 // Helper method for legacy API to obtain first component that implements
153 // the given trait. This is useful for routing commands that have no component
154 // path specified.
155 // Returns empty string if no components are found.
156 // This method only searches for component on the top level of components
157 // tree. No sub-components are searched.
158 std::string FindComponentWithTrait(const std::string& trait) const override;
159
Alex Vakulenko6b394d12015-12-05 15:52:54 -0800160 // Support for legacy APIs. Setting command and state definitions.
161 // This translates into modifying a trait definition.
162 bool AddLegacyCommandDefinitions(const base::DictionaryValue& dict,
163 ErrorPtr* error) override;
164 bool AddLegacyStateDefinitions(const base::DictionaryValue& dict,
165 ErrorPtr* error) override;
166 // Returns device state for legacy APIs.
167 const base::DictionaryValue& GetLegacyState() const override;
168 // Returns command definitions for legacy APIs.
169 const base::DictionaryValue& GetLegacyCommandDefinitions() const override;
170
Alex Vakulenkoba981152015-12-05 13:58:22 -0800171 private:
172 // A helper method to find a JSON element of component at |path| to add new
173 // sub-components to.
174 base::DictionaryValue* FindComponentGraftNode(const std::string& path,
175 ErrorPtr* error);
176 base::DictionaryValue* FindMutableComponent(const std::string& path,
177 ErrorPtr* error);
178
Alex Vakulenko6b394d12015-12-05 15:52:54 -0800179 // Legacy API support: Helper function to support state/command definitions.
180 // Adds the given trait to at least one component.
181 // Searches for available components and if none of them already supports this
182 // trait, it adds it to the first available component.
183 void AddTraitToLegacyComponent(const std::string& trait);
184
Alex Vakulenkoba981152015-12-05 13:58:22 -0800185 // Helper method to find a sub-component given a root node and a relative path
186 // from the root to the target component.
187 static const base::DictionaryValue* FindComponentAt(
188 const base::DictionaryValue* root,
189 const std::string& path,
190 ErrorPtr* error);
191
Vitaly Bukaece713e2015-12-09 10:59:33 -0800192 base::DefaultClock default_clock_;
Alex Vakulenkoba981152015-12-05 13:58:22 -0800193 base::Clock* clock_{nullptr};
Vitaly Buka41aa8092015-12-09 20:04:34 -0800194
Alex Vakulenkod91d6252015-12-05 17:14:39 -0800195 // An ID of last state change update. Each NotifyPropertiesUpdated()
196 // invocation increments this value by 1.
197 UpdateID last_state_change_id_{0};
198 // Callback list for state change queue event sinks.
199 // This member must be defined before |command_queue_|.
200 base::CallbackList<void(UpdateID)> on_server_state_updated_;
201
Alex Vakulenkoba981152015-12-05 13:58:22 -0800202 base::DictionaryValue traits_; // Trait definitions.
203 base::DictionaryValue components_; // Component instances.
204 CommandQueue command_queue_; // Command queue containing command instances.
205 std::vector<base::Closure> on_trait_changed_;
206 std::vector<base::Closure> on_componet_tree_changed_;
207 std::vector<base::Closure> on_state_changed_;
208 uint32_t next_command_id_{0};
Alex Vakulenkoba981152015-12-05 13:58:22 -0800209 std::map<std::string, std::unique_ptr<StateChangeQueue>> state_change_queues_;
Alex Vakulenkoba981152015-12-05 13:58:22 -0800210
Alex Vakulenko6b394d12015-12-05 15:52:54 -0800211 // Legacy API support.
212 mutable base::DictionaryValue legacy_state_; // Device state.
213 mutable base::DictionaryValue legacy_command_defs_; // Command definitions.
214
Alex Vakulenkoba981152015-12-05 13:58:22 -0800215 DISALLOW_COPY_AND_ASSIGN(ComponentManagerImpl);
216};
217
218} // namespace weave
219
220#endif // LIBWEAVE_SRC_COMPONENT_MANAGER_IMPL_H_