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_COMMANDS_CLOUD_COMMAND_PROXY_H_
6 #define LIBWEAVE_SRC_COMMANDS_CLOUD_COMMAND_PROXY_H_
7 
8 #include <deque>
9 #include <memory>
10 #include <string>
11 #include <utility>
12 
13 #include <base/macros.h>
14 #include <base/memory/weak_ptr.h>
15 #include <base/scoped_observer.h>
16 #include <weave/command.h>
17 
18 #include "src/backoff_entry.h"
19 #include "src/commands/cloud_command_update_interface.h"
20 #include "src/commands/command_instance.h"
21 #include "src/component_manager.h"
22 
23 namespace weave {
24 
25 class CommandInstance;
26 
27 namespace provider {
28 class TaskRunner;
29 }
30 
31 // Command proxy which publishes command updates to the cloud.
32 class CloudCommandProxy : public CommandInstance::Observer {
33  public:
34   CloudCommandProxy(CommandInstance* command_instance,
35                     CloudCommandUpdateInterface* cloud_command_updater,
36                     ComponentManager* component_manager,
37                     std::unique_ptr<BackoffEntry> backoff_entry,
38                     provider::TaskRunner* task_runner);
39   ~CloudCommandProxy() override = default;
40 
41   // CommandProxyInterface implementation/overloads.
42   void OnCommandDestroyed() override;
43   void OnErrorChanged() override;
44   void OnProgressChanged() override;
45   void OnResultsChanged() override;
46   void OnStateChanged() override;
47 
48  private:
49   using UpdateQueueEntry = std::pair<ComponentManager::UpdateID,
50                                      std::unique_ptr<base::DictionaryValue>>;
51   // Puts a command update data into the update queue, and optionally sends an
52   // asynchronous request to GCD server to update the command resource, if there
53   // are no pending device status updates.
54   void QueueCommandUpdate(std::unique_ptr<base::DictionaryValue> patch);
55 
56   // Sends an asynchronous request to GCD server to update the command resource,
57   // if there are no pending device status updates.
58   void SendCommandUpdate();
59 
60   // Retry the last failed command update request to the server.
61   void ResendCommandUpdate();
62 
63   // Callback invoked by the asynchronous PATCH request to the server.
64   void OnUpdateCommandDone(ErrorPtr error);
65 
66   // Callback invoked by the device state change queue to notify of the
67   // successful device state update. |update_id| is the ID of the state that
68   // has been updated on the server.
69   void OnDeviceStateUpdated(ComponentManager::UpdateID update_id);
70 
71   CommandInstance* command_instance_;
72   CloudCommandUpdateInterface* cloud_command_updater_;
73   ComponentManager* component_manager_;
74   provider::TaskRunner* task_runner_{nullptr};
75 
76   // Backoff for SendCommandUpdate() method.
77   std::unique_ptr<BackoffEntry> cloud_backoff_entry_;
78 
79   // Set to true while a pending PATCH request is in flight to the server.
80   bool command_update_in_progress_{false};
81   // Update queue with all the command update requests ready to be sent to
82   // the server.
83   std::deque<UpdateQueueEntry> update_queue_;
84 
85   // Callback token from the state change queue for OnDeviceStateUpdated()
86   // callback for ask the device state change queue to call when the state
87   // is updated on the server.
88   ComponentManager::Token callback_token_;
89 
90   // Last device state update ID that has been sent out to the server
91   // successfully.
92   ComponentManager::UpdateID last_state_update_id_{0};
93 
94   ScopedObserver<CommandInstance, CommandInstance::Observer> observer_{this};
95 
96   base::WeakPtrFactory<CloudCommandProxy> backoff_weak_ptr_factory_{this};
97   base::WeakPtrFactory<CloudCommandProxy> weak_ptr_factory_{this};
98   DISALLOW_COPY_AND_ASSIGN(CloudCommandProxy);
99 };
100 
101 }  // namespace weave
102 
103 #endif  // LIBWEAVE_SRC_COMMANDS_CLOUD_COMMAND_PROXY_H_
104