317 lines
8.4 KiB
C++
317 lines
8.4 KiB
C++
// 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.
|
|
|
|
#include "examples/daemon/common/daemon.h"
|
|
|
|
#include <weave/device.h>
|
|
|
|
#include <base/bind.h>
|
|
#include <base/memory/weak_ptr.h>
|
|
|
|
namespace {
|
|
|
|
const char kTraits[] = R"({
|
|
"onOff": {
|
|
"commands": {
|
|
"setConfig": {
|
|
"minimalRole": "user",
|
|
"parameters": {
|
|
"state": {
|
|
"type": "string",
|
|
"enum": [ "on", "standby" ]
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"state": {
|
|
"state": {
|
|
"type": "string",
|
|
"enum": [ "on", "standby" ],
|
|
"isRequired": true
|
|
}
|
|
}
|
|
},
|
|
"brightness": {
|
|
"commands": {
|
|
"setConfig": {
|
|
"minimalRole": "user",
|
|
"parameters": {
|
|
"brightness": {
|
|
"type": "integer",
|
|
"minimum": 0,
|
|
"maximum": 100
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"state": {
|
|
"brightness": {
|
|
"type": "integer",
|
|
"isRequired": true,
|
|
"minimum": 0,
|
|
"maximum": 100
|
|
}
|
|
}
|
|
},
|
|
"colorXY": {
|
|
"commands": {
|
|
"setConfig": {
|
|
"minimalRole": "user",
|
|
"parameters": {
|
|
"colorSetting": {
|
|
"type": "object",
|
|
"required": [
|
|
"colorX",
|
|
"colorY"
|
|
],
|
|
"properties": {
|
|
"colorX": {
|
|
"type": "number",
|
|
"minimum": 0.0,
|
|
"maximum": 1.0
|
|
},
|
|
"colorY": {
|
|
"type": "number",
|
|
"minimum": 0.0,
|
|
"maximum": 1.0
|
|
}
|
|
},
|
|
"additionalProperties": false
|
|
}
|
|
},
|
|
"errors": ["colorOutOfRange"]
|
|
}
|
|
},
|
|
"state": {
|
|
"colorSetting": {
|
|
"type": "object",
|
|
"isRequired": true,
|
|
"required": [ "colorX", "colorY" ],
|
|
"properties": {
|
|
"colorX": {
|
|
"type": "number",
|
|
"minimum": 0.0,
|
|
"maximum": 1.0
|
|
},
|
|
"colorY": {
|
|
"type": "number",
|
|
"minimum": 0.0,
|
|
"maximum": 1.0
|
|
}
|
|
}
|
|
},
|
|
"colorCapRed": {
|
|
"type": "object",
|
|
"isRequired": true,
|
|
"required": [ "colorX", "colorY" ],
|
|
"properties": {
|
|
"colorX": {
|
|
"type": "number",
|
|
"minimum": 0.0,
|
|
"maximum": 1.0
|
|
},
|
|
"colorY": {
|
|
"type": "number",
|
|
"minimum": 0.0,
|
|
"maximum": 1.0
|
|
}
|
|
}
|
|
},
|
|
"colorCapGreen": {
|
|
"type": "object",
|
|
"isRequired": true,
|
|
"required": [ "colorX", "colorY" ],
|
|
"properties": {
|
|
"colorX": {
|
|
"type": "number",
|
|
"minimum": 0.0,
|
|
"maximum": 1.0
|
|
},
|
|
"colorY": {
|
|
"type": "number",
|
|
"minimum": 0.0,
|
|
"maximum": 1.0
|
|
}
|
|
}
|
|
},
|
|
"colorCapBlue": {
|
|
"type": "object",
|
|
"isRequired": true,
|
|
"required": [ "colorX", "colorY" ],
|
|
"properties": {
|
|
"colorX": {
|
|
"type": "number",
|
|
"minimum": 0.0,
|
|
"maximum": 1.0
|
|
},
|
|
"colorY": {
|
|
"type": "number",
|
|
"minimum": 0.0,
|
|
"maximum": 1.0
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
})";
|
|
|
|
const char kDefaultState[] = R"({
|
|
"colorXY": {
|
|
"colorSetting": {"colorX": 0, "colorY": 0},
|
|
"colorCapRed": {"colorX": 0.674, "colorY": 0.322},
|
|
"colorCapGreen":{"colorX": 0.408, "colorY": 0.517},
|
|
"colorCapBlue": {"colorX": 0.168, "colorY": 0.041}
|
|
}
|
|
})";
|
|
|
|
const char kComponent[] = "light";
|
|
|
|
} // anonymous namespace
|
|
|
|
// LightHandler is a command handler example that shows
|
|
// how to handle commands for a Weave light.
|
|
class LightHandler {
|
|
public:
|
|
LightHandler() = default;
|
|
void Register(weave::Device* device) {
|
|
device_ = device;
|
|
|
|
device->AddTraitDefinitionsFromJson(kTraits);
|
|
CHECK(device->AddComponent(kComponent, {"onOff", "brightness", "colorXY"},
|
|
nullptr));
|
|
CHECK(
|
|
device->SetStatePropertiesFromJson(kComponent, kDefaultState, nullptr));
|
|
UpdateLightState();
|
|
|
|
device->AddCommandHandler(kComponent, "onOff.setConfig",
|
|
base::Bind(&LightHandler::OnOnOffSetConfig,
|
|
weak_ptr_factory_.GetWeakPtr()));
|
|
device->AddCommandHandler(kComponent, "brightness.setConfig",
|
|
base::Bind(&LightHandler::OnBrightnessSetConfig,
|
|
weak_ptr_factory_.GetWeakPtr()));
|
|
device->AddCommandHandler(kComponent, "colorXY.setConfig",
|
|
base::Bind(&LightHandler::OnColorXYSetConfig,
|
|
weak_ptr_factory_.GetWeakPtr()));
|
|
}
|
|
|
|
private:
|
|
void OnBrightnessSetConfig(const std::weak_ptr<weave::Command>& command) {
|
|
auto cmd = command.lock();
|
|
if (!cmd)
|
|
return;
|
|
LOG(INFO) << "received command: " << cmd->GetName();
|
|
const auto& params = cmd->GetParameters();
|
|
int32_t brightness_value = 0;
|
|
if (params.GetInteger("brightness", &brightness_value)) {
|
|
// Display this command in terminal.
|
|
LOG(INFO) << cmd->GetName() << " brightness: " << brightness_value;
|
|
|
|
if (brightness_state_ != brightness_value) {
|
|
brightness_state_ = brightness_value;
|
|
UpdateLightState();
|
|
}
|
|
cmd->Complete({}, nullptr);
|
|
return;
|
|
}
|
|
weave::ErrorPtr error;
|
|
weave::Error::AddTo(&error, FROM_HERE, "invalid_parameter_value",
|
|
"Invalid parameters");
|
|
cmd->Abort(error.get(), nullptr);
|
|
}
|
|
|
|
void OnOnOffSetConfig(const std::weak_ptr<weave::Command>& command) {
|
|
auto cmd = command.lock();
|
|
if (!cmd)
|
|
return;
|
|
LOG(INFO) << "received command: " << cmd->GetName();
|
|
const auto& params = cmd->GetParameters();
|
|
std::string requested_state;
|
|
if (params.GetString("state", &requested_state)) {
|
|
LOG(INFO) << cmd->GetName() << " state: " << requested_state;
|
|
|
|
bool new_light_status = requested_state == "on";
|
|
if (new_light_status != light_status_) {
|
|
light_status_ = new_light_status;
|
|
|
|
LOG(INFO) << "Light is now: " << (light_status_ ? "ON" : "OFF");
|
|
UpdateLightState();
|
|
}
|
|
cmd->Complete({}, nullptr);
|
|
return;
|
|
}
|
|
weave::ErrorPtr error;
|
|
weave::Error::AddTo(&error, FROM_HERE, "invalid_parameter_value",
|
|
"Invalid parameters");
|
|
cmd->Abort(error.get(), nullptr);
|
|
}
|
|
|
|
void OnColorXYSetConfig(const std::weak_ptr<weave::Command>& command) {
|
|
auto cmd = command.lock();
|
|
if (!cmd)
|
|
return;
|
|
LOG(INFO) << "received command: " << cmd->GetName();
|
|
const auto& params = cmd->GetParameters();
|
|
const base::DictionaryValue* colorXY = nullptr;
|
|
if (params.GetDictionary("colorSetting", &colorXY)) {
|
|
bool updateState = false;
|
|
double X = 0.0;
|
|
double Y = 0.0;
|
|
if (colorXY->GetDouble("colorX", &X)) {
|
|
color_X_ = X;
|
|
updateState = true;
|
|
}
|
|
|
|
if (colorXY->GetDouble("colorY", &Y)) {
|
|
color_Y_ = Y;
|
|
updateState = true;
|
|
}
|
|
|
|
if (updateState)
|
|
UpdateLightState();
|
|
|
|
cmd->Complete({}, nullptr);
|
|
return;
|
|
}
|
|
|
|
weave::ErrorPtr error;
|
|
weave::Error::AddTo(&error, FROM_HERE, "invalid_parameter_value",
|
|
"Invalid parameters");
|
|
cmd->Abort(error.get(), nullptr);
|
|
}
|
|
|
|
void UpdateLightState() {
|
|
base::DictionaryValue state;
|
|
state.SetString("onOff.state", light_status_ ? "on" : "standby");
|
|
state.SetInteger("brightness.brightness", brightness_state_);
|
|
|
|
std::unique_ptr<base::DictionaryValue> colorXY(new base::DictionaryValue());
|
|
colorXY->SetDouble("colorX", color_X_);
|
|
colorXY->SetDouble("colorY", color_Y_);
|
|
state.Set("colorXY.colorSetting", colorXY.release());
|
|
device_->SetStateProperties(kComponent, state, nullptr);
|
|
}
|
|
|
|
weave::Device* device_{nullptr};
|
|
|
|
// Simulate the state of the light.
|
|
bool light_status_{false};
|
|
int32_t brightness_state_{0};
|
|
double color_X_{0.0};
|
|
double color_Y_{0.0};
|
|
base::WeakPtrFactory<LightHandler> weak_ptr_factory_{this};
|
|
};
|
|
|
|
int main(int argc, char** argv) {
|
|
Daemon::Options opts;
|
|
opts.model_id_ = "AIAAA";
|
|
if (!opts.Parse(argc, argv)) {
|
|
Daemon::Options::ShowUsage(argv[0]);
|
|
return 1;
|
|
}
|
|
Daemon daemon{opts};
|
|
LightHandler handler;
|
|
handler.Register(daemon.GetDevice());
|
|
daemon.Run();
|
|
return 0;
|
|
}
|