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 #include "examples/daemon/common/daemon.h"
6 
7 #include <weave/device.h>
8 
9 #include <base/bind.h>
10 #include <base/memory/weak_ptr.h>
11 
12 namespace {
13 
14 const char kTraits[] = R"({
15   "onOff": {
16     "commands": {
17       "setConfig": {
18         "minimalRole": "user",
19         "parameters": {
20           "state": {
21             "type": "string",
22             "enum": [ "on", "standby" ]
23           }
24         }
25       }
26     },
27     "state": {
28       "state": {
29         "type": "string",
30         "enum": [ "on", "standby" ],
31         "isRequired": true
32       }
33     }
34   },
35   "volume": {
36     "commands": {
37       "setConfig": {
38         "minimalRole": "user",
39         "parameters": {
40           "volume": {
41             "type": "integer",
42             "minimum": 0,
43             "maximum": 100
44           },
45           "isMuted": { "type": "boolean" }
46         }
47       }
48     },
49     "state": {
50       "isMuted": {
51         "type": "boolean",
52         "isRequired": true
53       },
54       "volume": {
55         "type": "integer",
56         "minimum": 0,
57         "maximum": 100,
58         "isRequired": true
59       }
60     }
61   }
62 })";
63 
64 const char kComponent[] = "speaker";
65 
66 }  // anonymous namespace
67 
68 // SpeakerHandler is a command handler example that shows
69 // how to handle commands for a Weave speaker.
70 class SpeakerHandler {
71  public:
72   SpeakerHandler() = default;
Register(weave::Device * device)73   void Register(weave::Device* device) {
74     device_ = device;
75 
76     device->AddTraitDefinitionsFromJson(kTraits);
77     CHECK(device->AddComponent(kComponent, {"onOff", "volume"}, nullptr));
78     UpdateSpeakerState();
79 
80     device->AddCommandHandler(kComponent, "onOff.setConfig",
81                               base::Bind(&SpeakerHandler::OnOnOffSetConfig,
82                                          weak_ptr_factory_.GetWeakPtr()));
83     device->AddCommandHandler(kComponent, "volume.setConfig",
84                               base::Bind(&SpeakerHandler::OnVolumeSetConfig,
85                                          weak_ptr_factory_.GetWeakPtr()));
86   }
87 
88  private:
OnVolumeSetConfig(const std::weak_ptr<weave::Command> & command)89   void OnVolumeSetConfig(const std::weak_ptr<weave::Command>& command) {
90     auto cmd = command.lock();
91     if (!cmd)
92       return;
93     LOG(INFO) << "received command: " << cmd->GetName();
94 
95     const auto& params = cmd->GetParameters();
96     // Handle volume parameter
97     int32_t volume_value = 0;
98     if (params.GetInteger("volume", &volume_value)) {
99       // Display this command in terminal.
100       LOG(INFO) << cmd->GetName() << " volume: " << volume_value;
101 
102       if (volume_value_ != volume_value) {
103         volume_value_ = volume_value;
104         UpdateSpeakerState();
105       }
106       cmd->Complete({}, nullptr);
107       return;
108     }
109 
110     // Handle isMuted parameter
111     bool isMuted_status = false;
112     if (params.GetBoolean("isMuted", &isMuted_status)) {
113       // Display this command in terminal.
114       LOG(INFO) << cmd->GetName() << " is "
115                 << (isMuted_status ? "muted" : "not muted");
116 
117       if (isMuted_status_ != isMuted_status) {
118         isMuted_status_ = isMuted_status;
119 
120         LOG(INFO) << "Speaker is now: "
121                   << (isMuted_status ? "muted" : "not muted");
122         UpdateSpeakerState();
123       }
124     }
125 
126     cmd->Complete({}, nullptr);
127   }
128 
OnOnOffSetConfig(const std::weak_ptr<weave::Command> & command)129   void OnOnOffSetConfig(const std::weak_ptr<weave::Command>& command) {
130     auto cmd = command.lock();
131     if (!cmd)
132       return;
133     LOG(INFO) << "received command: " << cmd->GetName();
134     const auto& params = cmd->GetParameters();
135     std::string requested_state;
136     if (params.GetString("state", &requested_state)) {
137       LOG(INFO) << cmd->GetName() << " state: " << requested_state;
138 
139       bool new_speaker_status = requested_state == "on";
140       if (new_speaker_status != speaker_status_) {
141         speaker_status_ = new_speaker_status;
142 
143         LOG(INFO) << "Speaker is now: " << (speaker_status_ ? "ON" : "OFF");
144         UpdateSpeakerState();
145       }
146     }
147     cmd->Complete({}, nullptr);
148   }
149 
UpdateSpeakerState()150   void UpdateSpeakerState() {
151     base::DictionaryValue state;
152     state.SetString("onOff.state", speaker_status_ ? "on" : "standby");
153     state.SetBoolean("volume.isMuted", isMuted_status_);
154     state.SetInteger("volume.volume", volume_value_);
155     device_->SetStateProperties(kComponent, state, nullptr);
156   }
157 
158   weave::Device* device_{nullptr};
159 
160   // Simulate the state of the speaker.
161   bool speaker_status_;
162   bool isMuted_status_;
163   int32_t volume_value_;
164   base::WeakPtrFactory<SpeakerHandler> weak_ptr_factory_{this};
165 };
166 
main(int argc,char ** argv)167 int main(int argc, char** argv) {
168   Daemon::Options opts;
169   if (!opts.Parse(argc, argv)) {
170     Daemon::Options::ShowUsage(argv[0]);
171     return 1;
172   }
173   Daemon daemon{opts};
174   SpeakerHandler speaker;
175   speaker.Register(daemon.GetDevice());
176   daemon.Run();
177   return 0;
178 }
179