Home | History | Annotate | Download | only in light
      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   "brightness": {
     36     "commands": {
     37       "setConfig": {
     38         "minimalRole": "user",
     39         "parameters": {
     40           "brightness": {
     41             "type": "integer",
     42             "minimum": 0,
     43             "maximum": 100
     44           }
     45         }
     46       }
     47     },
     48     "state": {
     49       "brightness": {
     50         "type": "integer",
     51         "isRequired": true,
     52         "minimum": 0,
     53         "maximum": 100
     54       }
     55     }
     56   },
     57   "colorXY": {
     58     "commands": {
     59       "setConfig": {
     60         "minimalRole": "user",
     61         "parameters": {
     62           "colorSetting": {
     63             "type": "object",
     64             "required": [
     65               "colorX",
     66               "colorY"
     67             ],
     68             "properties": {
     69               "colorX": {
     70                 "type": "number",
     71                 "minimum": 0.0,
     72                 "maximum": 1.0
     73               },
     74               "colorY": {
     75                 "type": "number",
     76                 "minimum": 0.0,
     77                 "maximum": 1.0
     78               }
     79             },
     80             "additionalProperties": false
     81           }
     82         },
     83         "errors": ["colorOutOfRange"]
     84       }
     85     },
     86     "state": {
     87       "colorSetting": {
     88         "type": "object",
     89         "isRequired": true,
     90         "required": [ "colorX", "colorY" ],
     91         "properties": {
     92           "colorX": {
     93             "type": "number",
     94             "minimum": 0.0,
     95             "maximum": 1.0
     96           },
     97           "colorY": {
     98             "type": "number",
     99             "minimum": 0.0,
    100             "maximum": 1.0
    101           }
    102         }
    103       },
    104       "colorCapRed": {
    105         "type": "object",
    106         "isRequired": true,
    107         "required": [ "colorX", "colorY" ],
    108         "properties": {
    109           "colorX": {
    110             "type": "number",
    111             "minimum": 0.0,
    112             "maximum": 1.0
    113           },
    114           "colorY": {
    115             "type": "number",
    116             "minimum": 0.0,
    117             "maximum": 1.0
    118           }
    119         }
    120       },
    121       "colorCapGreen": {
    122         "type": "object",
    123         "isRequired": true,
    124         "required": [ "colorX", "colorY" ],
    125         "properties": {
    126           "colorX": {
    127             "type": "number",
    128             "minimum": 0.0,
    129             "maximum": 1.0
    130           },
    131           "colorY": {
    132             "type": "number",
    133             "minimum": 0.0,
    134             "maximum": 1.0
    135           }
    136         }
    137       },
    138       "colorCapBlue": {
    139         "type": "object",
    140         "isRequired": true,
    141         "required": [ "colorX", "colorY" ],
    142         "properties": {
    143           "colorX": {
    144             "type": "number",
    145             "minimum": 0.0,
    146             "maximum": 1.0
    147           },
    148           "colorY": {
    149             "type": "number",
    150             "minimum": 0.0,
    151             "maximum": 1.0
    152           }
    153         }
    154       }
    155     }
    156   }
    157 })";
    158 
    159 const char kDefaultState[] = R"({
    160   "colorXY": {
    161     "colorSetting": {"colorX": 0, "colorY": 0},
    162     "colorCapRed":  {"colorX": 0.674, "colorY": 0.322},
    163     "colorCapGreen":{"colorX": 0.408, "colorY": 0.517},
    164     "colorCapBlue": {"colorX": 0.168, "colorY": 0.041}
    165   }
    166 })";
    167 
    168 const char kComponent[] = "light";
    169 
    170 }  // anonymous namespace
    171 
    172 // LightHandler is a command handler example that shows
    173 // how to handle commands for a Weave light.
    174 class LightHandler {
    175  public:
    176   LightHandler() = default;
    177   void Register(weave::Device* device) {
    178     device_ = device;
    179 
    180     device->AddTraitDefinitionsFromJson(kTraits);
    181     CHECK(device->AddComponent(kComponent, {"onOff", "brightness", "colorXY"},
    182                                nullptr));
    183     CHECK(
    184         device->SetStatePropertiesFromJson(kComponent, kDefaultState, nullptr));
    185     UpdateLightState();
    186 
    187     device->AddCommandHandler(kComponent, "onOff.setConfig",
    188                               base::Bind(&LightHandler::OnOnOffSetConfig,
    189                                          weak_ptr_factory_.GetWeakPtr()));
    190     device->AddCommandHandler(kComponent, "brightness.setConfig",
    191                               base::Bind(&LightHandler::OnBrightnessSetConfig,
    192                                          weak_ptr_factory_.GetWeakPtr()));
    193     device->AddCommandHandler(kComponent, "colorXY.setConfig",
    194                               base::Bind(&LightHandler::OnColorXYSetConfig,
    195                                          weak_ptr_factory_.GetWeakPtr()));
    196   }
    197 
    198  private:
    199   void OnBrightnessSetConfig(const std::weak_ptr<weave::Command>& command) {
    200     auto cmd = command.lock();
    201     if (!cmd)
    202       return;
    203     LOG(INFO) << "received command: " << cmd->GetName();
    204     const auto& params = cmd->GetParameters();
    205     int32_t brightness_value = 0;
    206     if (params.GetInteger("brightness", &brightness_value)) {
    207       // Display this command in terminal.
    208       LOG(INFO) << cmd->GetName() << " brightness: " << brightness_value;
    209 
    210       if (brightness_state_ != brightness_value) {
    211         brightness_state_ = brightness_value;
    212         UpdateLightState();
    213       }
    214       cmd->Complete({}, nullptr);
    215       return;
    216     }
    217     weave::ErrorPtr error;
    218     weave::Error::AddTo(&error, FROM_HERE, "invalid_parameter_value",
    219                         "Invalid parameters");
    220     cmd->Abort(error.get(), nullptr);
    221   }
    222 
    223   void OnOnOffSetConfig(const std::weak_ptr<weave::Command>& command) {
    224     auto cmd = command.lock();
    225     if (!cmd)
    226       return;
    227     LOG(INFO) << "received command: " << cmd->GetName();
    228     const auto& params = cmd->GetParameters();
    229     std::string requested_state;
    230     if (params.GetString("state", &requested_state)) {
    231       LOG(INFO) << cmd->GetName() << " state: " << requested_state;
    232 
    233       bool new_light_status = requested_state == "on";
    234       if (new_light_status != light_status_) {
    235         light_status_ = new_light_status;
    236 
    237         LOG(INFO) << "Light is now: " << (light_status_ ? "ON" : "OFF");
    238         UpdateLightState();
    239       }
    240       cmd->Complete({}, nullptr);
    241       return;
    242     }
    243     weave::ErrorPtr error;
    244     weave::Error::AddTo(&error, FROM_HERE, "invalid_parameter_value",
    245                         "Invalid parameters");
    246     cmd->Abort(error.get(), nullptr);
    247   }
    248 
    249   void OnColorXYSetConfig(const std::weak_ptr<weave::Command>& command) {
    250     auto cmd = command.lock();
    251     if (!cmd)
    252       return;
    253     LOG(INFO) << "received command: " << cmd->GetName();
    254     const auto& params = cmd->GetParameters();
    255     const base::DictionaryValue* colorXY = nullptr;
    256     if (params.GetDictionary("colorSetting", &colorXY)) {
    257       bool updateState = false;
    258       double X = 0.0;
    259       double Y = 0.0;
    260       if (colorXY->GetDouble("colorX", &X)) {
    261         color_X_ = X;
    262         updateState = true;
    263       }
    264 
    265       if (colorXY->GetDouble("colorY", &Y)) {
    266         color_Y_ = Y;
    267         updateState = true;
    268       }
    269 
    270       if (updateState)
    271         UpdateLightState();
    272 
    273       cmd->Complete({}, nullptr);
    274       return;
    275     }
    276 
    277     weave::ErrorPtr error;
    278     weave::Error::AddTo(&error, FROM_HERE, "invalid_parameter_value",
    279                         "Invalid parameters");
    280     cmd->Abort(error.get(), nullptr);
    281   }
    282 
    283   void UpdateLightState() {
    284     base::DictionaryValue state;
    285     state.SetString("onOff.state", light_status_ ? "on" : "standby");
    286     state.SetInteger("brightness.brightness", brightness_state_);
    287 
    288     std::unique_ptr<base::DictionaryValue> colorXY(new base::DictionaryValue());
    289     colorXY->SetDouble("colorX", color_X_);
    290     colorXY->SetDouble("colorY", color_Y_);
    291     state.Set("colorXY.colorSetting", colorXY.release());
    292     device_->SetStateProperties(kComponent, state, nullptr);
    293   }
    294 
    295   weave::Device* device_{nullptr};
    296 
    297   // Simulate the state of the light.
    298   bool light_status_{false};
    299   int32_t brightness_state_{0};
    300   double color_X_{0.0};
    301   double color_Y_{0.0};
    302   base::WeakPtrFactory<LightHandler> weak_ptr_factory_{this};
    303 };
    304 
    305 int main(int argc, char** argv) {
    306   Daemon::Options opts;
    307   opts.model_id_ = "AIAAA";
    308   if (!opts.Parse(argc, argv)) {
    309     Daemon::Options::ShowUsage(argv[0]);
    310     return 1;
    311   }
    312   Daemon daemon{opts};
    313   LightHandler handler;
    314   handler.Register(daemon.GetDevice());
    315   daemon.Run();
    316   return 0;
    317 }
    318