Add support for state updates on ComponentManager
Implemented state support functionality from StateManager. Now the
ComponentManager object can replace StateManager, StatePackage,
CommandDictionary and CommandManager classes.
Most implementation was borrowed/adapted from existing StateManager
and StatePackage classes. And the interfaces were made compatible
with those two classes so the new ComponentManager can be used as
a drop-in replacement of the old classes.
BUG: 25841719
Change-Id: Ib981de1cf44c47a95594c56d78ac211812b3fa44
Reviewed-on: https://weave-review.googlesource.com/1780
Reviewed-by: Vitaly Buka <vitalybuka@google.com>
diff --git a/src/component_manager.h b/src/component_manager.h
index d9de8ea..2deaa30 100644
--- a/src/component_manager.h
+++ b/src/component_manager.h
@@ -5,21 +5,49 @@
#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_dictionary.h"
#include "src/commands/command_queue.h"
+#include "src/states/state_change_queue.h"
namespace weave {
class CommandInstance;
+// 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 final {
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();
+ explicit ComponentManager(base::Clock* clock);
~ComponentManager();
// Loads trait definition schema.
@@ -30,7 +58,7 @@
bool LoadTraits(const std::string& json, ErrorPtr* error);
// Sets callback which is called when new trait definitions are added.
- void AddTraitDefChanged(const base::Closure& callback);
+ void AddTraitDefChangedCallback(const base::Closure& callback);
// Adds a new component instance to device.
// |path| is a path to the parent component (or empty string if a root-level
@@ -51,6 +79,9 @@
const std::vector<std::string>& traits,
ErrorPtr* error);
+ // Sets callback which is called when new components are added.
+ void AddComponentTreeChangedCallback(const base::Closure& callback);
+
// 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.
@@ -102,11 +133,49 @@
// Returns the full JSON dictionary containing component instances.
const base::DictionaryValue& GetComponents() const { return components_; }
+ // Component state manipulation methods.
+ bool SetStateProperties(const std::string& component_path,
+ const base::DictionaryValue& dict,
+ ErrorPtr* error);
+ bool SetStatePropertiesFromJson(const std::string& component_path,
+ const std::string& json,
+ ErrorPtr* error);
+ const base::Value* GetStateProperty(const std::string& component_path,
+ const std::string& name,
+ ErrorPtr* error) const;
+ bool SetStateProperty(const std::string& component_path,
+ const std::string& name,
+ const base::Value& value,
+ ErrorPtr* error);
+
+ void AddStateChangedCallback(const base::Closure& callback);
+
+ // Returns the recorded state changes since last time this method was called.
+ StateSnapshot GetAndClearRecordedStateChanges();
+
+ // Called to notify that the state patch with |id| has been successfully sent
+ // to the server and processed.
+ void NotifyStateUpdatedOnServer(UpdateID id);
+
+ // Returns an ID of last state change update. Each SetStatePropertyNNN()
+ // invocation increments this value by 1.
+ UpdateID GetLastStateChangeId() const { return last_state_change_id_; }
+
+ // 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.
+ Token AddServerStateUpdatedCallback(
+ const base::Callback<void(UpdateID)>& callback);
+
private:
// A helper method to find a JSON element of component at |path| to add new
// sub-components to.
base::DictionaryValue* FindComponentGraftNode(const std::string& path,
ErrorPtr* error);
+ base::DictionaryValue* FindMutableComponent(const std::string& path,
+ ErrorPtr* error);
// Helper method to find a sub-component given a root node and a relative path
// from the root to the target component.
@@ -115,13 +184,22 @@
const std::string& path,
ErrorPtr* error);
-
+ base::Clock* clock_{nullptr};
base::DictionaryValue traits_; // Trait definitions.
base::DictionaryValue components_; // Component instances.
CommandQueue command_queue_; // Command queue containing command instances.
- std::vector<base::Callback<void()>> on_trait_changed_;
+ std::vector<base::Closure> on_trait_changed_;
+ std::vector<base::Closure> on_componet_tree_changed_;
+ std::vector<base::Closure> on_state_changed_;
uint32_t next_command_id_{0};
+ std::map<std::string, std::unique_ptr<StateChangeQueue>> state_change_queues_;
+ // An ID of last state change update. Each NotifyPropertiesUpdated()
+ // invocation increments this value by 1.
+ UpdateID last_state_change_id_{0};
+ // Callback list for state change queue event sinks.
+ base::CallbackList<void(UpdateID)> on_server_state_updated_;
+
DISALLOW_COPY_AND_ASSIGN(ComponentManager);
};