aboutsummaryrefslogtreecommitdiff
path: root/src/component_manager.h
blob: 1a3d05f8bd60a35311e3a977034bed730b8d9b3c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
// 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.

#ifndef LIBWEAVE_SRC_COMPONENT_MANAGER_H_
#define LIBWEAVE_SRC_COMPONENT_MANAGER_H_

#include <map>
#include <memory>

#include <base/callback_list.h>
#include <base/time/clock.h>
#include <base/values.h>
#include <weave/error.h>

#include "src/commands/command_queue.h"

namespace weave {

class CommandInstance;

enum class UserRole {
  kViewer,
  kUser,
  kManager,
  kOwner,
};

// A simple notification record event to track component state changes.
// The |timestamp| records the time of the state change.
// |changed_properties| contains a property set with the new property values
// which were updated at the time the event was recorded.
struct ComponentStateChange {
  ComponentStateChange(base::Time time,
                       const std::string& path,
                       std::unique_ptr<base::DictionaryValue> properties)
      : timestamp{time},
        component{path},
        changed_properties{std::move(properties)} {}
  base::Time timestamp;
  std::string component;
  std::unique_ptr<base::DictionaryValue> changed_properties;
};

class ComponentManager {
 public:
  using UpdateID = uint64_t;
  using Token =
      std::unique_ptr<base::CallbackList<void(UpdateID)>::Subscription>;
  struct StateSnapshot {
    UpdateID update_id;
    std::vector<ComponentStateChange> state_changes;
  };

  ComponentManager() {}
  virtual ~ComponentManager() {}

  // Loads trait definition schema.
  virtual bool LoadTraits(const base::DictionaryValue& dict,
                          ErrorPtr* error) = 0;

  // Same as the overload above, but takes a json string to read the trait
  // definitions from.
  virtual bool LoadTraits(const std::string& json, ErrorPtr* error) = 0;

  // Sets callback which is called when new trait definitions are added.
  virtual void AddTraitDefChangedCallback(const base::Closure& callback) = 0;

  // Adds a new component instance to device.
  // |path| is a path to the parent component (or empty string if a root-level
  // component is being added).
  // |name| is a component name being added.
  // |traits| is a list of trait names this component supports.
  virtual bool AddComponent(const std::string& path,
                            const std::string& name,
                            const std::vector<std::string>& traits,
                            ErrorPtr* error) = 0;

  // Adds a new component instance to device, as a part of component array.
  // |path| is a path to the parent component.
  // |name| is an array root element inside the child components.
  // |traits| is a list of trait names this component supports.
  virtual bool AddComponentArrayItem(const std::string& path,
                                     const std::string& name,
                                     const std::vector<std::string>& traits,
                                     ErrorPtr* error) = 0;

  // Removes an existing component instance from device.
  // |path| is a path to the parent component (or empty string if a root-level
  // component is being removed).
  // |name| is a name of the component to be removed.
  virtual bool RemoveComponent(const std::string& path,
                               const std::string& name,
                               ErrorPtr* error) = 0;

  // Removes an element from component array.
  // |path| is a path to the parent component.
  // |index| is a zero-based element index in the component array.
  virtual bool RemoveComponentArrayItem(const std::string& path,
                                        const std::string& name,
                                        size_t index,
                                        ErrorPtr* error) = 0;

  // Sets callback which is called when new components are added.
  virtual void AddComponentTreeChangedCallback(
      const base::Closure& callback) = 0;

  // Adds a new command instance to the command queue. The command specified in
  // |command_instance| must be fully initialized and have its name, component,
  // id populated.
  virtual void
  AddCommand(std::unique_ptr<CommandInstance> command_instance) = 0;

  // Parses the command definition from a json dictionary. The resulting command
  // instance is populated with all the required fields and partially validated
  // against syntax/schema.
  // The new command ID is returned through optional |id| param.
  virtual std::unique_ptr<CommandInstance> ParseCommandInstance(
      const base::DictionaryValue& command,
      Command::Origin command_origin,
      UserRole role,
      std::string* id,
      ErrorPtr* error) = 0;

  // Find a command instance with the given ID in the command queue.
  virtual CommandInstance* FindCommand(const std::string& id) = 0;

  // Command queue monitoring callbacks (called when a new command is added to
  // or removed from the queue).
  virtual void AddCommandAddedCallback(
      const CommandQueue::CommandCallback& callback) = 0;
  virtual void AddCommandRemovedCallback(
      const CommandQueue::CommandCallback& callback) = 0;

  // Adds a command handler for specific component's command.
  // |component_path| is a path to target component (e.g. "stove.burners[2]").
  // |command_name| is a full path of the command, including trait name and
  // command name (e.g. "burner.setPower").
  virtual void AddCommandHandler(
      const std::string& component_path,
      const std::string& command_name,
      const Device::CommandHandlerCallback& callback) = 0;

  // Finds a component instance by its full path.
  virtual const base::DictionaryValue* FindComponent(const std::string& path,
                                                     ErrorPtr* error) const = 0;
  // Finds a definition of trait with the given |name|.
  virtual const base::DictionaryValue* FindTraitDefinition(
      const std::string& name) const = 0;

  // Finds a command definition, where |command_name| is in the form of
  // "trait.command".
  virtual const base::DictionaryValue* FindCommandDefinition(
      const std::string& command_name) const = 0;

  // Checks the minimum required user role for a given command.
  virtual bool GetCommandMinimalRole(const std::string& command_name,
                                     UserRole* minimal_role,
                                     ErrorPtr* error) const = 0;

  // Checks the minimum required user role for a given state property.
  virtual bool GetStateMinimalRole(const std::string& state_property_name,
                                   UserRole* minimal_role,
                                   ErrorPtr* error) const = 0;

  // Returns the full JSON dictionary containing trait definitions.
  virtual const base::DictionaryValue& GetTraits() const = 0;

  // Returns the full JSON dictionary containing component instances.
  virtual const base::DictionaryValue& GetComponents() const = 0;

  // Returns a JSON dictionary containing component instances with state
  // properties visible to a user of the given |role|.
  virtual std::unique_ptr<base::DictionaryValue> GetComponentsForUserRole(
      UserRole role) const = 0;

  // Component state manipulation methods.
  virtual bool SetStateProperties(const std::string& component_path,
                                  const base::DictionaryValue& dict,
                                  ErrorPtr* error) = 0;
  virtual bool SetStatePropertiesFromJson(const std::string& component_path,
                                          const std::string& json,
                                          ErrorPtr* error) = 0;
  virtual const base::Value* GetStateProperty(const std::string& component_path,
                                              const std::string& name,
                                              ErrorPtr* error) const = 0;
  virtual bool SetStateProperty(const std::string& component_path,
                                const std::string& name,
                                const base::Value& value,
                                ErrorPtr* error) = 0;

  virtual void AddStateChangedCallback(const base::Closure& callback) = 0;

  // Returns the recorded state changes since last time this method was called.
  virtual StateSnapshot GetAndClearRecordedStateChanges() = 0;

  // Called to notify that the state patch with |id| has been successfully sent
  // to the server and processed.
  virtual void NotifyStateUpdatedOnServer(UpdateID id) = 0;

  // Returns an ID of last state change update. Each SetStatePropertyNNN()
  // invocation increments this value by 1.
  virtual UpdateID GetLastStateChangeId() const = 0;

  // Subscribes for device state update notifications from cloud server.
  // The |callback| will be called every time a state patch with given ID is
  // successfully received and processed by Weave server.
  // Returns a subscription token. As soon as this token is destroyed, the
  // respective callback is removed from the callback list.
  virtual Token AddServerStateUpdatedCallback(
      const base::Callback<void(UpdateID)>& callback) = 0;

  // Helper method for legacy API to obtain first component that implements
  // the given trait. This is useful for routing commands that have no component
  // path specified.
  // Returns empty string if no components are found.
  // This method only searches for component on the top level of components
  // tree. No sub-components are searched.
  virtual std::string FindComponentWithTrait(
      const std::string& trait) const = 0;

  DISALLOW_COPY_AND_ASSIGN(ComponentManager);
};

}  // namespace weave

#endif  // LIBWEAVE_SRC_COMPONENT_MANAGER_H_