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
23namespace weave {
24
25class CommandInstance;
26
27namespace provider {
28class TaskRunner;
29}
30
31// Command proxy which publishes command updates to the cloud.
32class 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