Fix new schema to match the new server definitions

A new server version now validates the state definitions in
traits as well as commands and some of our sample traits were
not defined properly. Also, the server now requires the 'base'
trait to be complete (and have base.reboot and base.identify
commands defined).

Change-Id: Icc576918895eba642498aa9b8bb1771825562f06
Reviewed-on: https://weave-review.googlesource.com/1971
Reviewed-by: Vitaly Buka <vitalybuka@google.com>
diff --git a/examples/daemon/ledflasher/ledflasher.cc b/examples/daemon/ledflasher/ledflasher.cc
index e63deac..d26728f 100644
--- a/examples/daemon/ledflasher/ledflasher.cc
+++ b/examples/daemon/ledflasher/ledflasher.cc
@@ -18,21 +18,21 @@
 const char kTraits[] = R"({
   "_ledflasher": {
     "commands": {
-      "_set": {
+      "set": {
         "minimalRole": "user",
         "parameters": {
-          "_led": {
+          "led": {
             "type": "integer",
             "minimum": 1,
             "maximum": 3
           },
-          "_on": { "type": "boolean" }
+          "on": { "type": "boolean" }
         }
       },
-      "_toggle": {
+      "toggle": {
         "minimalRole": "user",
         "parameters": {
-          "_led": {
+          "led": {
             "type": "integer",
             "minimum": 1,
             "maximum": 3
@@ -41,7 +41,7 @@
       }
     },
     "state": {
-      "_leds": {
+      "leds": {
         "type": "array",
         "items": { "type": "boolean" }
       }
@@ -66,11 +66,11 @@
     UpdateLedState();
 
     device->AddCommandHandler(
-        kComponent, "_ledflasher._toggle",
+        kComponent, "_ledflasher.toggle",
         base::Bind(&LedFlasherHandler::OnFlasherToggleCommand,
                    weak_ptr_factory_.GetWeakPtr()));
     device->AddCommandHandler(
-        kComponent, "_ledflasher._set",
+        kComponent, "_ledflasher.set",
         base::Bind(&LedFlasherHandler::OnFlasherSetCommand,
                    weak_ptr_factory_.GetWeakPtr()));
   }
@@ -134,7 +134,7 @@
     for (uint32_t i = 0; i < led_status_.size(); i++)
       list.AppendBoolean(led_status_[i] ? true : false);
 
-    device_->SetStateProperty(kComponent, "_ledflasher._leds", list, nullptr);
+    device_->SetStateProperty(kComponent, "_ledflasher.leds", list, nullptr);
   }
 
   weave::Device* device_{nullptr};
diff --git a/examples/daemon/light/light.cc b/examples/daemon/light/light.cc
index 035ef4e..298fcaf 100644
--- a/examples/daemon/light/light.cc
+++ b/examples/daemon/light/light.cc
@@ -27,7 +27,8 @@
     "state": {
       "state": {
         "type": "string",
-        "enum": [ "on", "standby" ]
+        "enum": [ "on", "standby" ],
+        "isRequired": true
       }
     }
   },
@@ -44,7 +45,14 @@
         }
       }
     },
-    "state": { "brightness": { "type": "integer" } }
+    "state": {
+      "brightness": {
+        "type": "integer",
+        "isRequired": true,
+        "minimum": 0,
+        "maximum": 100
+      }
+    }
   },
   "colorXY": {
     "commands": {
@@ -71,11 +79,15 @@
             },
             "additionalProperties": false
           }
-        }
+        },
+        "errors": ["colorOutOfRange"]
       }
     },
     "state": {
       "colorSetting": {
+        "type": "object",
+        "isRequired": true,
+        "required": [ "colorX", "colorY" ],
         "properties": {
           "colorX": {
             "type": "number",
@@ -90,6 +102,9 @@
         }
       },
       "colorCapRed": {
+        "type": "object",
+        "isRequired": true,
+        "required": [ "colorX", "colorY" ],
         "properties": {
           "colorX": {
             "type": "number",
@@ -104,6 +119,9 @@
         }
       },
       "colorCapGreen": {
+        "type": "object",
+        "isRequired": true,
+        "required": [ "colorX", "colorY" ],
         "properties": {
           "colorX": {
             "type": "number",
@@ -118,6 +136,9 @@
         }
       },
       "colorCapBlue": {
+        "type": "object",
+        "isRequired": true,
+        "required": [ "colorX", "colorY" ],
         "properties": {
           "colorX": {
             "type": "number",
diff --git a/examples/daemon/lock/lock.cc b/examples/daemon/lock/lock.cc
index 1137b92..0785c14 100644
--- a/examples/daemon/lock/lock.cc
+++ b/examples/daemon/lock/lock.cc
@@ -37,15 +37,20 @@
             "type": "string",
             "enum": [ "locked", "unlocked" ]
           }
-        }
+        },
+        "errors": ["batteryTooLow", "jammed", "lockingNotSupported"]
       }
     },
     "state": {
       "lockedState": {
         "type": "string",
-        "enum": [ "locked", "unlocked", "partiallyLocked" ]
+        "enum": [ "locked", "unlocked", "partiallyLocked" ],
+        "isRequired": true
       },
-      "isLockingSupported": { "type": "boolean" }
+      "isLockingSupported": {
+        "type": "boolean",
+        "isRequired": true
+      }
     }
   }
 })";
diff --git a/examples/daemon/oven/oven.cc b/examples/daemon/oven/oven.cc
index 151561d..ff1c60b 100644
--- a/examples/daemon/oven/oven.cc
+++ b/examples/daemon/oven/oven.cc
@@ -30,7 +30,50 @@
           "tempSetting": {
             "type": "number"
           }
-        }
+        },
+        "errors": ["tempOutOfRange", "unsupportedUnits"]
+      }
+    },
+    "state": {
+      "supportedUnits": {
+        "type": "array",
+        "items": {
+          "type": "string",
+          "enum": [ "celsius", "fahrenheit", "kelvin" ]
+        },
+        "minItems": 1,
+        "uniqueItems": true,
+        "isRequired": true
+      },
+      "units": {
+        "type": "string",
+        "enum": [ "celsius", "fahrenheit", "kelvin" ],
+        "isRequired": true
+      },
+      "tempSetting": {
+        "type": "number",
+        "isRequired": true
+      },
+      "maxTempSetting": {
+        "type": "number",
+        "isRequired": true
+      },
+      "minTempSetting": {
+        "type": "number",
+        "isRequired": true
+      }
+    }
+  },
+  "temperatureSensor": {
+    "commands": {
+      "setConfig": {
+        "minimalRole": "user",
+        "parameters": {
+          "units": {
+            "type": "string"
+          }
+        },
+        "errors": ["unsupportedUnits"]
       }
     },
     "state": {
@@ -43,40 +86,19 @@
             "fahrenheit",
             "kelvin"
           ]
-        }
+        },
+        "minItems": 1,
+        "uniqueItems": true,
+        "isRequired": true
       },
       "units": {
-        "type": "string"
-      },
-      "tempSetting": {
-        "type": "number"
-      },
-      "maxTempSetting": {
-        "type": "number"
-      },
-      "minTempSetting": {
-        "type": "number"
-      }
-    }
-  },
-  "temperatureSensor": {
-    "state": {
-      "supportedUnits": {
-        "type": "array",
-        "items": {
-          "type": "string",
-          "enum": [
-            "celsius",
-            "fahrenheit",
-            "kelvin"
-          ]
-        }
-      },
-      "units": {
-        "type": "string"
+        "type": "string",
+        "enum": [ "celsius", "fahrenheit", "kelvin" ],
+        "isRequired": true
       },
       "value": {
-        "type": "number"
+        "type": "number",
+        "isRequired": true
       }
     }
   },
@@ -95,7 +117,10 @@
     },
     "state": {
       "brightness": {
-        "type": "number"
+        "type": "integer",
+        "isRequired": true,
+        "minimum": 0,
+        "maximum": 100
       }
     }
   }
diff --git a/examples/daemon/sample/sample.cc b/examples/daemon/sample/sample.cc
index 2ab4b27..1d036d5 100644
--- a/examples/daemon/sample/sample.cc
+++ b/examples/daemon/sample/sample.cc
@@ -15,19 +15,20 @@
 const char kTraits[] = R"({
   "_sample": {
     "commands": {
-      "_hello": {
+      "hello": {
         "minimalRole": "user",
         "parameters": {
-          "_name": { "type": "string" }
+          "name": { "type": "string" }
         }
       },
-      "_ping": {
-        "minimalRole": "user"
+      "ping": {
+        "minimalRole": "user",
+        "parameters": {}
       },
-      "_countdown": {
+      "countdown": {
         "minimalRole": "user",
         "parameters": {
-          "_seconds": {
+          "seconds": {
             "type": "integer",
             "minimum": 1,
             "maximum": 25
@@ -36,7 +37,7 @@
       }
     },
     "state": {
-      "_ping_count": { "type": "integer" }
+      "pingCount": { "type": "integer" }
     }
   }
 })";
@@ -60,15 +61,15 @@
     device->AddTraitDefinitionsFromJson(kTraits);
     CHECK(device->AddComponent(kComponent, {"_sample"}, nullptr));
     CHECK(device->SetStatePropertiesFromJson(
-        kComponent, R"({"_sample": {"_ping_count": 0}})", nullptr));
+        kComponent, R"({"_sample": {"pingCount": 0}})", nullptr));
 
-    device->AddCommandHandler(kComponent, "_sample._hello",
+    device->AddCommandHandler(kComponent, "_sample.hello",
                               base::Bind(&SampleHandler::OnHelloCommand,
                                          weak_ptr_factory_.GetWeakPtr()));
-    device->AddCommandHandler(kComponent, "_sample._ping",
+    device->AddCommandHandler(kComponent, "_sample.ping",
                               base::Bind(&SampleHandler::OnPingCommand,
                                          weak_ptr_factory_.GetWeakPtr()));
-    device->AddCommandHandler(kComponent, "_sample._countdown",
+    device->AddCommandHandler(kComponent, "_sample.countdown",
                               base::Bind(&SampleHandler::OnCountdownCommand,
                                          weak_ptr_factory_.GetWeakPtr()));
   }
@@ -82,7 +83,7 @@
 
     const auto& params = cmd->GetParameters();
     std::string name;
-    if (!params.GetString("_name", &name)) {
+    if (!params.GetString("name", &name)) {
       weave::ErrorPtr error;
       weave::Error::AddTo(&error, FROM_HERE, "example",
                           "invalid_parameter_value", "Name is missing");
@@ -91,7 +92,7 @@
     }
 
     base::DictionaryValue result;
-    result.SetString("_reply", "Hello " + name);
+    result.SetString("reply", "Hello " + name);
     cmd->Complete(result, nullptr);
     LOG(INFO) << cmd->GetName() << " command finished: " << result;
   }
@@ -102,7 +103,7 @@
       return;
     LOG(INFO) << "received command: " << cmd->GetName();
 
-    device_->SetStateProperty(kComponent, "_sample._ping_count",
+    device_->SetStateProperty(kComponent, "_sample.pingCount",
                               base::FundamentalValue{++ping_count_}, nullptr);
     LOG(INFO) << "New component state: " << device_->GetComponents();
 
@@ -120,7 +121,7 @@
 
     const auto& params = cmd->GetParameters();
     int seconds;
-    if (!params.GetInteger("_seconds", &seconds))
+    if (!params.GetInteger("seconds", &seconds))
       seconds = 10;
 
     LOG(INFO) << "starting countdown";
@@ -133,13 +134,9 @@
       return;
 
     if (seconds > 0) {
-      const auto& params = cmd->GetParameters();
-      std::string todo;
-      params.GetString("_todo", &todo);
       LOG(INFO) << "countdown tick: " << seconds << " seconds left";
-
       base::DictionaryValue progress;
-      progress.SetInteger("_seconds_left", seconds);
+      progress.SetInteger("seconds_left", seconds);
       cmd->SetProgress(progress, nullptr);
       task_runner_->PostDelayedTask(
           FROM_HERE,
diff --git a/examples/daemon/speaker/speaker.cc b/examples/daemon/speaker/speaker.cc
index 8b3e41b..35eee2f 100644
--- a/examples/daemon/speaker/speaker.cc
+++ b/examples/daemon/speaker/speaker.cc
@@ -25,8 +25,11 @@
       }
     },
     "state": {
-      "type": "string",
-      "enum": [ "on", "standby" ]
+      "state": {
+        "type": "string",
+        "enum": [ "on", "standby" ],
+        "isRequired": true
+      }
     }
   },
   "volume": {
@@ -44,8 +47,16 @@
       }
     },
     "state": {
-      "isMuted": { "type": "boolean" },
-      "volume": { "type": "integer" }
+      "isMuted": {
+        "type": "boolean",
+        "isRequired": true
+      },
+      "volume": {
+        "type": "integer",
+        "minimum": 0,
+        "maximum": 100,
+        "isRequired": true
+      }
     }
   }
 })";
diff --git a/src/base_api_handler.cc b/src/base_api_handler.cc
index 9c64463..5562b6c 100644
--- a/src/base_api_handler.cc
+++ b/src/base_api_handler.cc
@@ -13,7 +13,7 @@
 namespace weave {
 
 namespace {
-const char kBaseComponent[] = "weave";
+const char kBaseComponent[] = "base";
 const char kBaseTrait[] = "base";
 const char kBaseStateFirmwareVersion[] = "base.firmwareVersion";
 const char kBaseStateAnonymousAccessRole[] = "base.localAnonymousAccessMaxRole";
@@ -55,13 +55,45 @@
               "type": "string"
             }
           }
+        },
+        "reboot": {
+          "minimalRole": "user",
+          "parameters": {},
+          "errors": ["notEnoughBattery"]
+        },
+        "identify": {
+          "minimalRole": "user",
+          "parameters": {}
         }
       },
       "state": {
-        "firmwareVersion": "string",
-        "localDiscoveryEnabled": "boolean",
-        "localAnonymousAccessMaxRole": [ "none", "viewer", "user" ],
-        "localPairingEnabled": "boolean"
+        "firmwareVersion": {
+          "type": "string",
+          "isRequired": true
+        },
+        "localDiscoveryEnabled": {
+          "type": "boolean",
+          "isRequired": true
+        },
+        "localAnonymousAccessMaxRole": {
+          "type": "string",
+          "enum": [ "none", "viewer", "user" ],
+        "isRequired": true
+        },
+        "localPairingEnabled": {
+          "type": "boolean",
+          "isRequired": true
+        },
+        "connectionStatus": {
+          "type": "string"
+        },
+        "network": {
+          "type": "object",
+          "additionalProperties": false,
+          "properties": {
+            "name": { "type": "string" }
+          }
+        }
       }
     }
   })");
diff --git a/src/base_api_handler_unittest.cc b/src/base_api_handler_unittest.cc
index e0ebf88..6f8460b 100644
--- a/src/base_api_handler_unittest.cc
+++ b/src/base_api_handler_unittest.cc
@@ -133,14 +133,46 @@
             "type": "string"
           }
         }
+      },
+      "reboot": {
+        "minimalRole": "user",
+        "parameters": {},
+        "errors": ["notEnoughBattery"]
+      },
+      "identify": {
+        "minimalRole": "user",
+        "parameters": {}
       }
     },
-   "state": {
-      "firmwareVersion": "string",
-      "localAnonymousAccessMaxRole": [ "none", "viewer", "user" ],
-      "localDiscoveryEnabled": "boolean",
-      "localPairingEnabled": "boolean"
-   }
+    "state": {
+      "firmwareVersion": {
+        "type": "string",
+        "isRequired": true
+      },
+      "localDiscoveryEnabled": {
+        "type": "boolean",
+        "isRequired": true
+      },
+      "localAnonymousAccessMaxRole": {
+        "type": "string",
+        "enum": [ "none", "viewer", "user" ],
+        "isRequired": true
+      },
+      "localPairingEnabled": {
+        "type": "boolean",
+        "isRequired": true
+      },
+      "connectionStatus": {
+        "type": "string"
+      },
+      "network": {
+        "type": "object",
+        "additionalProperties": false,
+        "properties": {
+          "name": { "type": "string" }
+        }
+      }
+    }
   })";
   EXPECT_JSON_EQ(expected, *trait);
 }
@@ -150,7 +182,7 @@
 
   AddCommand(R"({
     'name' : 'base.updateBaseConfiguration',
-    'component': 'weave',
+    'component': 'base',
     'parameters': {
       'localDiscoveryEnabled': false,
       'localAnonymousAccessMaxRole': 'none',
@@ -171,7 +203,7 @@
 
   AddCommand(R"({
     'name' : 'base.updateBaseConfiguration',
-    'component': 'weave',
+    'component': 'base',
     'parameters': {
       'localDiscoveryEnabled': true,
       'localAnonymousAccessMaxRole': 'user',
@@ -205,7 +237,7 @@
 TEST_F(BaseApiHandlerTest, UpdateDeviceInfo) {
   AddCommand(R"({
     'name' : 'base.updateDeviceInfo',
-    'component': 'weave',
+    'component': 'base',
     'parameters': {
       'name': 'testName',
       'description': 'testDescription',
@@ -220,7 +252,7 @@
 
   AddCommand(R"({
     'name' : 'base.updateDeviceInfo',
-    'component': 'weave',
+    'component': 'base',
     'parameters': {
       'location': 'newLocation'
     }
diff --git a/src/device_registration_info.cc b/src/device_registration_info.cc
index 47fa40c..e70b8ba 100644
--- a/src/device_registration_info.cc
+++ b/src/device_registration_info.cc
@@ -512,9 +512,6 @@
     channel->SetString("supportedType", "pull");
   }
   resource->Set("channel", channel.release());
-  resource->Set("commandDefs",
-                component_manager_->GetLegacyCommandDefinitions().DeepCopy());
-  resource->Set("state", component_manager_->GetLegacyState().DeepCopy());
   resource->Set("traits", component_manager_->GetTraits().DeepCopy());
   resource->Set("components", component_manager_->GetComponents().DeepCopy());
 
diff --git a/src/device_registration_info_unittest.cc b/src/device_registration_info_unittest.cc
index 8be0c97..327c440 100644
--- a/src/device_registration_info_unittest.cc
+++ b/src/device_registration_info_unittest.cc
@@ -430,73 +430,41 @@
             EXPECT_TRUE(json->GetString("deviceDraft.name", &value));
             EXPECT_EQ("Coffee Pot", value);
             base::DictionaryValue* dict = nullptr;
-            EXPECT_TRUE(json->GetDictionary("deviceDraft.commandDefs", &dict));
-            auto expectedCommandDefs = R"({
-            'base': {
-              'reboot': {
-                'parameters': {
-                  'delay': {
-                    'minimum': 10,
-                    'type': 'integer'
-                  }
-                },
-                'minimalRole': 'user'
-              }
-            },
-            'robot': {
-              '_jump': {
-                'parameters': {
-                  '_height': {
-                    'type': 'integer'
-                  }
-                },
-                'minimalRole': 'user'
-              }
-            }
-          })";
-            EXPECT_JSON_EQ(expectedCommandDefs, *dict);
-
-            EXPECT_TRUE(json->GetDictionary("deviceDraft.state", &dict));
-            auto expectedState = R"({
-            'base': {
-              'firmwareVersion': '1.0'
-            }
-          })";
-            EXPECT_JSON_EQ(expectedState, *dict);
-
+            EXPECT_FALSE(json->GetDictionary("deviceDraft.commandDefs", &dict));
+            EXPECT_FALSE(json->GetDictionary("deviceDraft.state", &dict));
             EXPECT_TRUE(json->GetDictionary("deviceDraft.traits", &dict));
             auto expectedTraits = R"({
-            'base': {
-              'commands': {
-                'reboot': {
-                  'parameters': {'delay': {'minimum': 10, 'type': 'integer'}},
-                  'minimalRole': 'user'
+              'base': {
+                'commands': {
+                  'reboot': {
+                    'parameters': {'delay': {'minimum': 10, 'type': 'integer'}},
+                    'minimalRole': 'user'
+                  }
+                },
+                'state': {
+                  'firmwareVersion': {'type': 'string'}
                 }
               },
-              'state': {
-                'firmwareVersion': {'type': 'string'}
-              }
-            },
-            'robot': {
-              'commands': {
-                '_jump': {
-                  'parameters': {'_height': {'type': 'integer'}},
-                  'minimalRole': 'user'
+              'robot': {
+                'commands': {
+                  '_jump': {
+                    'parameters': {'_height': {'type': 'integer'}},
+                    'minimalRole': 'user'
+                  }
                 }
               }
-            }
-          })";
+            })";
             EXPECT_JSON_EQ(expectedTraits, *dict);
 
             EXPECT_TRUE(json->GetDictionary("deviceDraft.components", &dict));
             auto expectedComponents = R"({
-            'comp': {
-              'traits': ['base', 'robot'],
-              'state': {
-                'base': { 'firmwareVersion': '1.0' }
+              'comp': {
+                'traits': ['base', 'robot'],
+                'state': {
+                  'base': { 'firmwareVersion': '1.0' }
+                }
               }
-            }
-          })";
+            })";
             EXPECT_JSON_EQ(expectedComponents, *dict);
 
             base::DictionaryValue json_resp;